影子DOM是为自定义Web 组件设计的,为此需要支持嵌套DOM片段。从概念上讲,可以这么说:
位于影子宿主中的HTML需要一种机制以渲染到影子DOM中去,但这些HTML又不必属于影子DOM树。
默认情况下,嵌套内容会隐藏。来看下面的例子,其中的文本在1000 毫秒后会被隐藏:
document.body.innerHTML = `
Foo
会在1000 毫秒后变成空的。 为了显示文本内容,需要使用标签指示浏览器在哪里放置原来的HTML。下面的代码修改 了前面的例子,让影子宿主中的文本出现在了影子DOM 中: document.body.innerHTML = `
`; document.querySelector('div') .attachShadow({ mode: 'open' }) .innerHTML = `
Foo
` 现在,投射进去的内容就像自己存在于影子DOM 中一样。检查页面会发现原来的内容实际上替代 了:
`; document.querySelector('div') .attachShadow({ mode: 'open' }) .innerHTML = `
` console.log(document.querySelector('p').parentElement); //
下面是使用槽位(slot)改写的前面红/绿/蓝子树的例子: for (let color of ['red', 'green', 'blue']) { const divElement = document.createElement('div'); divElement.innerText = `Make me ${color}`; document.body.appendChild(divElement) divElement .attachShadow({ mode: 'open' }) .innerHTML = `
`; } 除了默认槽位,还可以使用命名槽位(named slot)实现多个投射。这是通过匹配的slot/name 属性对实现的。带有slot="foo"属性的元素会被投射到带有name="foo"的上。下面的例子演 示了如何改变影子宿主子元素的渲染顺序: document.body.innerHTML = `
`; document.querySelector('div') .attachShadow({ mode: 'open' }) .innerHTML = ` `; // Renders: // Bar // Foo
#shadow-root (open)
注意,虽然在页面检查窗口中看到内容在影子DOM中,但这实际上只是DOM内容的投射(projection)。 实际的元素仍然处于外部DOM中: document.body.innerHTML = `
Foo
Foo
Foo
Bar