阴影 DOM 和 ReactJS

Shadow DOM and ReactJS

我在我的应用程序中使用网络组件。在 Web 组件中,我需要插入一个 React 组件。 Web 组件有阴影 DOM。当我尝试使用以下方法渲染反应组件时出现错误。

comp = React.createElement(ReactElem, {
    config: config,
    onRender: handleRender
});

ReactDOM.render(comp , self.shadowRoot.querySelector('#app1'));

错误

target container is not a dom element

我尝试使用 Web 组件 API 的 content,但随后它呈现在顶部而不是组件内部。任何线索如何使 React 组件在阴影中呈现 DOM?

如果您想将它插入网络组件的阴影 DOM 中,首先 select 组件(例如使用 querySelector),然后是其包含的阴影(shadowRoot).简化示例:

// Create React Element.
class Example extends React.Component {
  onClick() {
    console.log('Shadow!')
  }
  render() {
    return(
      <div onClick={this.onClick}>Hello World!</div>
    );
  }
}

// Create web component with target div inside it.
const container = document.createElement('app');
document.body.appendChild(container);

// Add shadow root to component.
const shadow = document.querySelector('app').attachShadow({ mode: 'open' });

// Select the web component, then the shadowRoot.
const target = document.querySelector('app').shadowRoot;

ReactDOM.render(<Example />, target);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

嘿我的朋友,我花时间为我们制作了这个:

// ShadowRoot.js

import React from "react";

export class ShadowRoot extends React.Component {

    attachShadow(host) {
        if (host == null) {
            return;
        }
        host.attachShadow({mode: "open"});
        host.shadowRoot.innerHTML = host.innerHTML;
        host.innerHTML = "";
    }

    render() {
        return (
            <span ref={this.attachShadow}>
                {this.props.children}
            </span>
        );
    }

}

这样使用:

<ShadowRoot>
    // put stuff here you want inside shadow root
</ShadowRoot>

2 个需要考虑的事项:

  • class React.Component 比挂钩等价物工作得更好
  • innerHTML 有点老套,状态更新不适用于此组件

看起来这个答案有点过时了,要将 Web 组件附加到 React 应用程序,您需要先将您的 Web 组件转换为模块。您可以通过使用类似 $) npm publish --access public

将其推送到 NPM 来完成此操作

这会将您的 Web 组件发布为 public NPM 模块,可以使用 npm install 下载 web-components-name-here。

现在您的代码已在构建时合并。您还需要采取一个步骤,那就是将其添加到您的根反应文件或 inxex.js--

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import { defineCustomElements } from 'your-custom--web-components/loader/index.js';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

defineCustomElements(window)

最后一段代码是将 npm 模块中的所有 Web 组件添加到 Reactjs 的全局范围的地方。现在您可以继续使用--

import React from 'react';
import './ReactFakeComp.css';
import ReactFakeComp from './App'; 

export default ReactFakeComp() {
   render(
        <your-custom--web-components />
   );
}    

您应用中的任何位置,就像常规 HTML 组件一样。

最后一件事,如果您是构建 npm 模块和发布它们的新手,我不想让这最后一部分劝阻您。我发现了一个叫做 Stencil 的工具,这是一个强大的工具,可以让你在一个隔离的环境中构建 Web 组件。它会自动创建所有其他额外的数据和文件,您需要使用导入以 CommonJS 或更新的 ES^ 语法发布您的 Web 组件。

但最重要的功能是您现在可以在 Typescript 中构建您的 Web 组件。我直接说没有更多的模板。 Stencil 将为您转换和构建一切。