声享正努力加载中...
$王江波
Web Components
Shadow DOM 解决了构建网络应用的脆弱性问题。脆弱性是由 HTML、CSS 和 JS 的全局性引起的。
Shadow DOM 修复了 CSS 和 DOM。它在网络平台中引入作用域样式。 无需工具或命名约定,您即可使用原生 JavaScript 捆绑 CSS 和标记、隐藏实现详情以及编写独立的组件。
DOM的背景知识
浏览器在加载网页的时候,会做一步DOM树的渲染,将 HTML(静态文本字符串)解析为数据模型(对象/节点)
与我们编写的静态 HTML 不同,浏览器生成的节点包含有属性、方法,可以通过程序进行操作!
使用JavaScript创建DOM的方法是 createElement('tagName'),创建后通过appendChild(element)方法插入到DOM树中。
const header = document.createElement('header');
const h1 = document.createElement('h1');
h1.textContent = 'Hello world!';
header.appendChild(h1);
document.body.appendChild(header);<body>
<header>
<h1>Hello DOM</h1>
</header>
</body>什么是Shadow DOM
Shadow DOM也是DOM节点,但加了自己的几点特性
什么是Shadow DOM
需要了解几个概念:
创建 Shadow DOM
创建 Shadow DOM 总共分几步?
const header = document.createElement('header');
const shadowRoot = header.attachShadow({mode: 'open'});
shadowRoot.innerHTML = '<h1>Hello Shadow DOM</h1>';
// header.shadowRoot === shadowRoot
// shadowRoot.host === header什么是组合
在网络开发世界中,组合是指我们如何使用 HTML 来通过声明构建应用。
组合是 <select>、<details>、<form> 和 <video> 等原生元素如此灵活的原因所在。 这些标记中的每个标记接受特定的 HTML 作为子项,并且加以特殊处理。
例如,<select> 知道如何将 <option> 和 <optgroup> 渲染为下拉和多选小部件。甚至 <video> 知道如何处理特定的子项:<source> 元素未进行渲染
关于组合
需要了解几个术语:
<button is="better-button">
<img src="gear.svg" slot="icon">
<span>Settings</span>
</button>#shadow-root
<style>...</style>
<slot name="icon"></slot>
<span id="wrapper">
<slot>Button</slot>
</span><button is="better-button">
#shadow-root
<style>...</style>
<slot name="icon">
<img src="gear.svg" slot="icon">
</slot>
<slot>
<span>Settings</span>
</slot>
</button>Slot 标签
Shadow DOM 使用 <slot> 元素将不同的 DOM 树组合在一起。
Slot 是组件内部的占位符,用户可以使用自己的标记来填充。
局部作用域样式
shadow DOM 最有用的功能是作用域 CSS
样式化Shadow DOM
设定样式的途径
事件模型
有些元素可以传递到外部:
使用自定义事件
如果影子树处于打开状态,调用 event.composedPath() 将返回事件经过的一组节点。
通过影子树中内部节点触发的自定义 DOM 事件不会超出影子边界,除非事件是使用 composed: true 标记创建的:
container.addEventListener('click', () => {
alert('点击 container');
container.dispatchEvent(new Event('containerchanged', {bubbles: true, composed: true}));
})
console.log(root);
root.host.addEventListener('containerchanged', () => {
console.log(event.composedPath());
alert('外部获取到Shadow DOM事件');
})使用自定义元素
创建自定义元素时,Shadow DOM 尤其有用。使用 shadow DOM 来分隔元素的 HTML、CSS 和 JS,从而生成一个“网络组件”。
customElements.define('fancy-tabs', class extends HTMLElement {
constructor() {
super();
const shadowRoot = this.attachShadow({mode: 'open'});
shadowRoot.innerHTML = `
<style>#tabs { ... }</style> <!-- styles are scoped to fancy-tabs! -->
<div id="tabs">...</div>
<div id="panels">...</div>
`;
}
});
