什么是shadow DOM
shadow DOM是Web Components的四大组件之一,它可以将一个隐藏的、独立的DOM添加到一个元素上,用来创建基于组件的应用。
Shadow DOM 与普通 DOM 相同,但有两点区别:
- 创建/使用的方式
- 与页面其他部分有关的行为方式。
通常,您创建 DOM 节点并将其附加至其他元素作为子项。 借助于 shadow DOM,您可以创建作用域 DOM 树,该 DOM 树附加至该元素上,但与其自身真正的子项分离开来。这一作用域子树称为影子树。被附着的元素称为影子宿主。 您在影子中添加的任何项均将成为宿主元素的本地项,包括 <style>。 这就是 shadow DOM 实现 CSS 样式作用域的方式。
shadow DOM特点
- 隔离 DOM:组件的 DOM 是独立的(例如,document.querySelector() 不会返回组件 shadow DOM 中的节点)。
- 作用域 CSS:shadow DOM 内部定义的 CSS 在其作用域内。样式规则不会泄漏,页面样式也不会渗入。
- 组合:为组件设计一个声明性、基于标记的 API。
- 简化 CSS - 作用域 DOM 意味着您可以使用简单的 CSS 选择器,更通用的 id/类名称,而无需担心命名冲突。
- 效率 - 将应用看成是多个 DOM 块,而不是一个大的(全局性)页面。
shadow DOM的使用
创建一个shadow DOM,继承自 HTMLElement
,在构造函数可以创建和操作dom
class ToolTip extends HTMLElement {
constructor() {
super();
var shadow = this.attachShadow({ mode: 'open' });
var header = document.createElement('h1');
header.className = 'shadow-dom-header';
header.innerHTML = 'shadow dom';
var style = document.createElement('style');
style.textContent = `.shadow-dom-header { color: red; }`;
shadow.appendChild(style);
shadow.appendChild(header);
}
}
customElements.define('tool-tip', ToolTip);
使用的方法跟原始的html标签一样
<tool-tip></tool-tip>
生成的dom结构和效果如下
shadow DOM的样式是独立开的,不会受到外界的 class 的影响,内部也不会影响到外部的样式
slot元素
Shadow DOM 使用 <slot> 元素将不同的 DOM 树组合在一起。Slot 是组件内部的占位符,其实用法跟 vue 相似,可能是 vue 采用的这种思想哈。
如果 <slot> 引入了元素,则这些元素可 “跨越” shadow DOM 的边界。 这些元素称为分布式节点。从概念上来看,分布式节点似乎有点奇怪。 Slot 实际上并不移动 DOM;它们在 shadow DOM 内部的其他位置进行渲染。
这句话比较难理解,我们先来尝试下如何使用 slot ,首先在上述的构造函数里面创建一个 slot
let slot = document.createElement('slot');
shadow.appendChild(slot);
使用 tool-tip 组件
<tool-tip>
<div>i'm a div</div>
</tool-tip>
可以看出 tool-tip
的子元素 div 会插在 shadow-root 的外部