ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
[TOC] ## 概述 1. 自定义元素的名称必须包含连词线 如`<user-card>`不能写成`<usercard>` ### Shadow DOM 特性: 1. 封装性:Shadow DOM 允许将组件的样式和结构封装在一起,避免了与全局样式和 JavaScript 的冲突。 2. 隔离性:Shadow DOM 的内容在外部页面上下文中是不可见的,从而确保组件的私有性。 3. 继承性:Shadow DOM 内的样式可以继承外部样式,并且外部样式也可以影响到 Shadow DOM 内的样式。 ## 指南 ### 自定义元素生命周期回调 ``` connectedCallback():每当元素添加到文档中时调用。规范建议开发人员尽可能在此回调中实现自定义元素的设定,而不是在构造函数中实现。 disconnectedCallback():每当元素从文档中移除时调用。 adoptedCallback():每当元素被移动到新文档中时调用。 attributeChangedCallback():在属性更改、添加、移除或替换时调用。有关此回调的更多详细信息,请 ``` 示例 ``` // 为这个元素创建类 class MyCustomElement extends HTMLElement { static observedAttributes = ["color", "size"]; constructor() { // 必须首先调用 super 方法 super(); } connectedCallback() { console.log("自定义元素添加至页面。"); } disconnectedCallback() { console.log("自定义元素从页面中移除。"); } adoptedCallback() { console.log("自定义元素移动至新页面。"); } attributeChangedCallback(name, oldValue, newValue) { console.log(`属性 ${name} 已变更。`); } } customElements.define("my-custom-element", MyCustomElement); ``` ### 注册自定义元素 **方式一:** 注册 ``` window.customElements.define("word-count", WordCount, { extends: "p" }); ``` 使用 ``` <p is="word-count"></p> ``` **方式二:** 注册 ``` window.customElements.define("popup-info", PopupInfo); ``` 使用 ``` <popup-info> <!-- 元素的内容 --> </popup-info> ``` ### 响应属性变化 * 一个名为`observedAttributes`的静态属性。这必须是一个包含元素需要变更通知的所有属性名称的数组。 * `attributeChangedCallback()`生命周期回调的实现。 示例 ``` // 为这个元素创建类 class MyCustomElement extends HTMLElement { static observedAttributes = ["size"]; constructor() { super(); } attributeChangedCallback(name, oldValue, newValue) { console.log(`属性 ${name} 已由 ${oldValue} 变更为 ${newValue}。`); } } customElements.define("my-custom-element", MyCustomElement); ``` 调用 ``` <my-custom-element size="100"></my-custom-element> ``` > size 在首次初始化时也会调用attributeChangedCallback ## 影子DOM 相关术语 ``` 影子宿主(Shadow host): 影子 DOM 附加到的常规 DOM 节点。 影子树(Shadow tree): 影子 DOM 内部的 DOM 树。 影子边界(Shadow boundary): 影子 DOM 终止,常规 DOM 开始的地方。 影子根(Shadow root): 影子树的根节点。 ``` ### 创建影子DOM ``` //html <div id="host"></div> <span>I'm not in the shadow DOM</span> //js const host = document.querySelector("#host"); const shadow = host.attachShadow({ mode: "open" }); const span = document.createElement("span"); span.textContent = "I'm in the shadow DOM"; shadow.appendChild(span); ``` > 此时如果更改全局根据 span 的样式,则影子的DOM 中的span 不会更改 `{ mode: "open" }` 参数说明 启用 open,则可以通过`host.shadowRoot.querySelectorAll("span")` 找到 span, 如果设置为 close,则找不到 ## 插槽 ``` <my-paragraph> <span slot="my-text">让我们使用一些不同的文本!</span> </my-paragraph> ```