【发布时间】:2021-04-06 14:42:50
【问题描述】:
我正在尝试从 react 组件构建 web 组件,一切正常,但我正在尝试解决两个问题:
- 有没有办法将此类 web 组件转换为纯 web 组件(使用 webpack、transpile 或其他方式),从而不捆绑 react 和其他依赖项?
- 有没有办法只包含所需的依赖部分,或者只包含所有/无,并且必须使用 webpack 的外部设置来使用主机的版本?
谢谢
【问题讨论】:
标签: reactjs web-component
我正在尝试从 react 组件构建 web 组件,一切正常,但我正在尝试解决两个问题:
谢谢
【问题讨论】:
标签: reactjs web-component
对于第一个问题,没有直接的方法可以将 React 组件转换为 Web 组件。您必须将其包装到 Web 组件类:
export function MyReactComponent() {
return (
<div>
Hello world
</div>
);
}
class MyWebComponent extends HTMLElement {
constructor() {
super();
// Do something more
}
connectedCallback() {
// Create a ShadowDOM
const root = this.attachShadow({ mode: 'open' });
// Create a mount element
const mountPoint = document.createElement('div');
root.appendChild(mountPoint);
// You can directly use shadow root as a mount point
ReactDOM.render(<MyReactComponent />, mountPoint);
}
}
customElements.define('my-web-component', MyWebComponent);
当然,您可以将其概括并创建一个可重用的函数:
function register(MyReactComponent, name) {
const WebComponent = class extends HTMLElement {
constructor() {
super();
// Do something more
}
connectedCallback() {
// Create a ShadowDOM
const root = this.attachShadow({ mode: 'open' });
// Create a mount element
const mountPoint = document.createElement('div');
root.appendChild(mountPoint);
// You can directly use shadow root as a mount point
ReactDOM.render(<MyReactComponent />, mountPoint);
}
}
customElements.define(name, MyWebComponent);
}
register(MyReactComponent, 'my-web-component');
现在可以在您想要作为 Web 组件公开的所有组件中重复使用相同的注册函数。此外,如果您的组件接受应该传递的道具,则可以将此函数更改为接受第三个参数作为字符串数组,其中每个值将使用Object.define 注册为此组件的设置器。每次调用 setter 时,您只需再次调用 ReactDOM.render。
现在对于第二个问题,您尝试做的事情有多种情况。
import 或 require。库的捆绑有点棘手,因为您必须决定输出格式是什么(common.js、ES 模块或 UMD 或全局或多种格式)。如果您为浏览器捆绑,理想的格式是 ES 模块,因为它可以更好地摇树。 Webpack 以前不支持 Module 格式,最近开始支持它。一般来说,我推荐 Webpack 用于应用程序,而 Rollup.js 用于库。
【讨论】:
React 不是用于构建原生 Web 组件的库。
手工编写 web 组件也不是最好的选择,因为它不能处理条件、循环、状态更改、虚拟 dom 和其他开箱即用的基本功能。
React、Vue Svelte 和其他自定义库当然有一些优点,而原生 Web 组件具有许多其他优势,例如生态系统简单性以及被浏览器和 W3C 移植。
一些库可以帮助您以现代且方便的方式编写本机 Web 组件:
如果你真的想将 React 组件包装到原生 Web 组件中,你可以这样做:
class MyComponent extends HTMLElement {
constructor() {
this.innerHTML = '<MyReactComponent />'
}
}
customElements.define('my-component', MyComponent)
并在您的 HTML 页面中使用它<my-component />
【讨论】: