浅谈Web Component

发布时间:2023年12月17日

Web Component是HTML5推出的一个新特征,就是web组件,它描述的其实是三种不同的的API:自定义元素,Shadow DOM和HTML模板.

  • 自定义元素: 在 HTML 基础标签外扩展自定义标签元素

  • Shadow DOM: 主要用于将 Shadow DOM 的内容与外层document DOM 隔离

  • HTML 模板: 使用 <template> 来定义组件模板,使用 <slot> 作为插槽使用

Custom Elements

class DiyButton extends HTMLElement {
  constructor() {
    super();
    let value = this.getAttribute("value");
    // 可以直接放入到innerHTML中
    // this.innerHTML = `<button>custom-button ${value}</button>`

    // 也可以通过appendChild的方式添加元素对象
    let btn = document.createElement("button");
    btn.innerHTML = `custom-button ${value}`;
    btn.addEventListener('click', () => { 
      this.setAttribute("name", "testtest");
      this.setAttribute("value", 9999);
    })
    this.appendChild(btn);
  }
  // 当 custom element首次被插入文档DOM时,被调用
  connectedCallback() {
    console.log("connectedCallback");
  }
  // 当 custom element从文档DOM中删除时,被调用
  disconnectedCallback() {
    console.log("disconnectedCallback");
  }
  // 当 custom element增加、删除、修改自身属性时,被调用
  attributeChangedCallback(name, oldValue, newValue) {
    console.log("attribute", name, oldValue, newValue);
  }
  // 声明需要监听的属性名,只有这些属性变化时才会触发attributeChangedCallback
  static get observedAttributes() {
    return ["name", "url", "value"];
  }
}
//参数一:自定义元素名,格式有要求:短线连接的字符串
//参数二:自定义元素构造器
//参数三:可选,含有 extends 属性的对象。指定所创建的元素继承自哪个内置元素,可以继承任何内置元素
window.customElements.define("Diy-button", DiyButton );


页面使用

<!DOCTYPE html>
<html lang="en">
  <body>
    <button>点击</button>
    <diy-button
      name="app-button"
      url="www.baidu.com"
      value="90"
    ></diy-button>
  </body>
  <script src="diy.js"></script>
  <script>
    const customButton = document.querySelector("diy-button");
    //要注意,写在这里是整个自定义元素的事件,也就是说,自定义元素里面的每一个元素,都会触发click事件
    customButton.addEventListener("click", function (e) {
      this.setAttribute("name", "test");
      this.setAttribute("value", 99);
    });
  </script>
</html>

Shadow DOM

Shadow DOM 是 Web components 的一个重要属性是封装——可以将标记结构、样式和行为隐藏起来, 并与页面上的其他代码相隔离,保证不同的部分不会混在一起,可使代码更加干净、整洁。其中,Shadow DOM 接口是关键所在,它可以将一个隐藏的、独立的 DOM 附加到一个元素上。

class DiyButton extends HTMLElement {
  constructor() {
    super();
    let btn = document.createElement("button");
    btn.innerHTML = `Diy-button ${value}`;
    //其他代码省略只保留关键代码...
    
    
    //创建Shadow DOM时,可以选择open或closed模式,
    //close会对外部DOM隐藏shadowRoot,这可以防止其他脚本对DOM的以外操作
    //除非有特殊需求,建议默认open
    this.attachShadow({ mode: "open" });
    //这里的样式,只会作用域当前的shadowRoot中,不会影响到外部的DOM
    this.shadowRoot.innerHTML = `
      <style>
        button {
          color: red;
        }
      </style>
    `;
    this.shadowRoot.appendChild(btn);
  }
  //其他代码省略只保留关键代码
}

HTML 模板

<template id="add-template">
  <input type="text">
  <button>新增</button>
</template>
class DiyButton extends HTMLElement {
  constructor() {
    super();
    let value = this.getAttribute("value");
    
    let templateEle = document.getElementById("add-template");
    let cloneEle = templateEle.content.cloneNode(true);
    cloneEle.querySelector("input[type='text']").value = `${value}`;

    let btn = document.createElement("button");
    btn.innerHTML = `custom-button ${value}`;
    btn.addEventListener('click', () => { 
      this.setAttribute("name", "test");
      this.setAttribute("value", 89);
    })
    
    this.attachShadow({ mode: "open" });
    this.shadowRoot.innerHTML = `
      <style>
        button {
          color: red;
        }
      </style>
    `;
    this.shadowRoot.appendChild(btn);
    
    this.shadowRoot.appendChild(cloneEle);
  }
}

还能使用slot插槽

<template id="add-template">
  <slot name="title"></slot>
  <input type="text">
  <button>新增</button>
</template>

<Diy-button
  name="app-button"
  url="www.baidu.com"
  value="90"
>
  <div slot="title">
    <h2>新增</h2>
  </div>
</Diy-button>
文章来源:https://blog.csdn.net/qq_39341415/article/details/135044503
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。