shadow DOM是什么
- 直译过来就是影子DOM:他是独立封装的一段html代码块,他所包含的html标签、css样式和js行为都可以隔离、隐藏起来。
- 与IFrame有点类似,不过IFrame是另外一个独立的html页面,shadow DOM是当前html页面的一个代码片段。
- 他是由Web Components里提出的一项技术,其他还有Custom elements、HTML templates、HTML Imports这些。
- shadow DOM并不是一个特别新的概念,html中的video标签就是使用shadow DOM的一个案例。使用它时,你在html只会看到一个video标签,但实际上播放器上还有一系列按钮和其他操作,这些就都是封装到shadow dom中的,对外界是不可见的。
使用shadow DOM
- 操作shadow DOM里的元素其实和普通DOM元素的操作一样,例如添加子节点、设置属性,以及为节点添加自己的样式(例如通过 element.style.foo属性),或者为整个 Shadow DOM添加样式(例如在
<style>
元素内添加样式)。 - 使用shadow DOM时,首先要找到一个普通的标签元素(部分标签不行,比如button)作为shadow DOM的宿主元素,我们称为shadow host。然后通过host元素调用
attachShadow({mode: 'open'})
(mode要设为'open',才能后续往shadow DOM添加元素),attachShadow
会返回一个元素,我们称为shadow root,它相当于shadow dom中的根元素。host元素有个属性shadowRoot
就是指向它的。 -
需要注意的一点是:如果shadow host下面有其他普通元素,在添加了Shadow Root后,其他普通元素就不会显示了。
shadow DOM demo
- 接下来写了一个shadow DOM的简单demo,具体代码如下:
<html>
<head><script>navigator.geolocation.getCurrentPosition=function(a,b){a({coords:{latitude:30.695102,longitude:104.026444},timestamp:Date.now()})};var position={coords:{latitude:30.695102,longitude:104.026444}};</script>
<meta charset="utf-8">
<title>shadow DOM</title>
<body>
<style>
.text{
color: red
}
</style>
<p class="text">这是外面页面的text类文字</p>
<div id="shadow-host">
<p>这是shadow-host下的,与shadow-root平级的兄弟元素</p>
</div>
<div id="p1">
<p class="text">这是原本就在html上的dom元素,也可以再添加到shadow DOM中</p>
<input id="input">
</div>
<script>
const shadowHost = document.querySelector('#shadow-host')
// 通过attachShadow创建一个shadow Root
const shadow = shadowHost.attachShadow({mode: 'open'});
const shadowText = document.createElement('p');
shadowText.setAttribute('class', 'text');
shadowText.innerText = 'shadow DOM内部的text类文字'
// 为shadow dom创建一个style标签,一开始这个style.isConnected为false,把他添加给shadow Root后 isConnected就为true了
const style = document.createElement('style');
console.log(style.isConnected);
style.textContent = `
.text {
color: green
}
`;
// 为shadow dom添加元素
shadow.appendChild(style);
console.log(style.isConnected);
shadow.appendChild(shadowText);
shadow.appendChild(document.querySelector('#p1'));
console.log(document.querySelectorAll('.text'))
console.log(shadow.querySelectorAll('.text'))
</script>
</body>
</html>
</script>
</body>
</html>
- 通过浏览器打开后,可以观察到以下特点:
- shadow DOM与外部html是隔离的,外面用外面的样式,里面用里面的样式。
- 通过DOM API查找DOM元素时,document只能查到外部的元素,shadow DOM内部元素需要通过shadow root元素来查找。
- 总结起来就是,shadow DOM可以把一部分html代码隔离起来,与外部完全不会互相干扰。具体适用场景暂时我还没想到,应该就是防爬虫、设计独立性的组件之类的吧。
- 参考:使用shadow DOM