概念
官方:https://developer.mozilla.org/zh-CN/docs/Web/API/Web_components/Using_shadow_DOM
核心:影子 DOM(Shadow DOM)允许你将一个 DOM 树附加到一个元素上,并且使该树的内部对于在页面中运行的 JavaScript 和 CSS 是隐藏的。
如何创建 Shadow DOM
下面的页面包含两个元素,一个 id 属性为 “host” 的
元素,以及一个包含了一些文本的 元素:
<div id="host"></div>
<span>I'm not in the shadow DOM</span>
我们将把 Shadow DOM 插入到 id=host 的元素上
const host = document.querySelector("#host");
// 创建一个 shadow dom, open 表示dom内部的细节是可见的
const shadow = host.attachShadow({ mode: "open" });
// 创建 span 并添加文本
const span = document.createElement("span");
span.textContent = "I'm in the shadow DOM";
// 将 span 元素插入到 shadow dom
shadow.appendChild(span);
界面效果是这样的:
如果页面中代码有功能代码,会将文本设置为大写
则不会影响到 shadow dom 的文本
DEMO:
需求:
- 使用fetch拿到本地的html文件,并将 html 解析为DOM
- 将解析后的内容插入到 shadowRoot
import React, { useEffect, useRef, useState } from 'react';
import './App.css';function App() {const container = useRef(null);const [html, setHtml] = useState(null)const fetchHTML = () => {// 使用 fetch 加载 HTML 文件fetch(`${process.env.PUBLIC_URL}/demo.html`).then(response => {if (!response.ok) {throw new Error('Network response was not ok');}return response.text(); // 将响应处理为文本}).then(html => {setHtml(html)// 将html解析为domconst parser = new DOMParser();const doc = parser.parseFromString(html, 'text/html');//创建 shadowRootconst container = document.getElementById('host');const shadowRoot = container.attachShadow({ mode: 'open' });// 由于样式隔离 需要单独提取style 再插入// Shadow DOM 的样式是封闭的,需要显式地将样式添加到 Shadow DOM 中const styles = doc.querySelectorAll('style');styles.forEach(style => {shadowRoot.appendChild(style.cloneNode(true));});// 将解析后的内容插入到 shadowRoot 中while (doc.body.firstChild) {shadowRoot.appendChild(doc.body.firstChild);}}).catch(error => {console.error('There was a problem with the fetch operation:', error);});}fetchHTML()return (<div className="App"><div className="left"><pre><code>{html}</code></pre></div><div id='host' className="right" ref={container}></div></div>);
}export default App;