先描述下Web Components 允许开发者创建可重用的自定义元素,它们可以一起使用来创建封装功能的自定义元素,并可以像浏览器原生的元素一样在任何地方重用,而不必担心样式和 DOM 的冲突问题Shadow DOM(影子 DOM):一组 JavaScript API 用于将「影子 DOM 树」附加到元素上,与主文档 DOM 树隔离,并能控制其关联的功能。通过这种方式,可以保持元素的私有,并能不用担心「样式」与文档的其他部分发生冲突。问题隔离在 Shadow Root 中的元素上的事件无法被触发,当在 Shadow DOM 外部捕获时浏览器会对事件进行「重定向」,也就是说在 Shadow DOM 中发生的事件在外部捕获时将会使用 host 元素作为事件源。这将让 React 在处理合成事件时,不认为 ShadowDOM 中元素基于 JSX 语法绑定的事件被触发。样式隔离问题,意味着全局样式必须在每个前端组件挂载最近的 Shadow Root 下手动注入进 <style> 标签,否则的样式会被隔离(所有样式都必须在 Shawdow Root 下否则会被隔离);事件捕获解决方案ReactDOM.createPortal 有一个特性是「通过 createPortal 渲染的 DOM,事件可以从 Portal 的入口端冒泡上来」,通过这个关键特性,没有父子关系的 DOM ,合成事件能冒泡过来,那通过 createPortal 渲染到 Shadow DOM 中的元素的事件也能正常触发import React from "react";import ReactDOM from "react-dom"; export function ShadowContent({ root, children }) { return ReactDOM.createPortal(children, root);} export class ShadowView extends React.Component { state = { root: null }; setRoot = eleemnt => { const root = eleemnt.attachShadow({ mode: "open" }); this.setState({ root }); }; render() { const { children } = this.props; const { root } = this.state; return <div ref={this.setRoot}> {root && <ShadowContent root={root} > {children} </ShadowContent>} </div>; }} export class App extends React.Component { state = { message: '...' }; onBtnClick = () => { this.setState({ message: 'haha' }); } render() { const { message } = this.state; return <ShadowView> <div>{message}</div> <button onClick={this.onBtnClick}>单击我</button> </ShadowView> }} ReactDOM.render(<App />, document.getElementById("root"));样式隔离如果你是 JSS 方案// https://github.com/styled-components/styled-components/pull/1491 <StyleSheetManager target={target.shadowRoot}> <React.Fragment> {/* your children here */} </React.Fragment> </StyleSheetManager>全局样式问题:每个组件最近的 Shadow Root 下手动注入一遍全局样式感觉可行的,Polymer 3.0 <dom-module>元素进行样式模块化,但是 <style include="..."> 的本质依旧是拷贝,无法与全局样式共享。https://polymer-library.polym...使用 ReactDOM.createPortal 我还解决了这个问题:🔥 如何优雅地解决多个 React、Vue App 之间的状态共享?——————————————————————————————————————————————————如果能够对你有帮助就请「点赞」「采纳」吧,感谢 🙏
先描述下
问题
事件捕获解决方案
样式隔离
使用 ReactDOM.createPortal 我还解决了这个问题:🔥 如何优雅地解决多个 React、Vue App 之间的状态共享?
——————————————————————————————————————————————————
如果能够对你有帮助就请「点赞」「采纳」吧,感谢 🙏