Shadow DOM
所谓 Shadow DOM 指的是,浏览器将模板、样式表、属性、JavaScript 码等,封装成一个独立的 DOM 元素。外部的设置无法影响到其内部,而内部的设置也不会影响到外部,与浏览器处理原生网页元素(比如<video>
元素)的方式很像。
Shadow DOM 最大的好处有两个,一是可以向用户隐藏细节,直接提供组件,二是可以封装内部样式表,不会影响到外部。
Custom Element 内部有一个 Shadow Root。它就是接入外部 DOM 的根元素。
// attachShadow() creates a shadow root.
let shadow = div.attachShadow({ mode: 'open' });
let inner = document.createElement('b');
inner.appendChild(document.createTextNode('Hiding in the shadows'));
// shadow root supports the normal appendChild method.
shadow.appendChild(inner);
div.querySelector('b'); // empty
上面代码中,<div>
包含<b>
,但是 DOM 方法无法看到它,而且页面的样式也影响不到它。
mode: 'open'
表示开发者工具里面,可以看到 Custom HTML 内部的 DOM,并与之互动。mode: closed
将不允许 Custom Element 的使用者与内部代码互动。
Shadow root 内部通过指定innerHTML
属性或使用<template>
元素,指定 HTML 代码。
Shadow DOM 内部可以通过向根添加<style>
(或<link>
)来设置样式。
let style = document.createElement('style');
style.innerText = 'b { font-weight: bolder; color: red; }';
shadowRoot.appendChild(style);
let inner = document.createElement('b');
inner.innerHTML = "I'm bolder in the shadows";
shadowRoot.appendChild(inner);
上面代码添加的样式,只会影响 Shadow DOM 内的元素。
Custom Element 的 CSS 样式内部,:root
表示这个根元素。比如,Custom Element 默认是行内元素,下面代码可以改成块级元素。
:host {
display: block;
}
:host([disabled]) {
opacity: 0.5;
}
注意,外部样式会覆盖掉:host
的设置,比如下面的样式会覆盖:host
。
my-element {
display: inline-block;
}
利用 CSS 的自定义属性,可以为 Custom Element 可以被覆盖的默认样式。下面是外部样式,my-element
是 Custom Element。
my-element {
--background-color: #ff0000;
}
然后,内部可以指定默认样式,用于用户没有指定颜色的情况。
:host {
--background-color: #ffffff;
}
#container {
background-color: var(--background-color);
}
下面的例子是为 Shadow DOM 加上独立的模板。
<div id="nameTag">张三</div>
<template id="nameTagTemplate">
<style>
.outer {
border: 2px solid brown;
}
</style>
<div class="outer">
<div class="boilerplate">
Hi! My name is
</div>
<div class="name">
Bob
</div>
</div>
</template>
上面代码是一个div
元素和模板。接下来,就是要把模板应用到div
元素上。