浅谈Web Component

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>

相关推荐

  1. 低代码

    2023-12-17 19:30:01       42 阅读
  2. Web Component

    2023-12-17 19:30:01       32 阅读
  3. react hooks

    2023-12-17 19:30:01       39 阅读
  4. 命令模式

    2023-12-17 19:30:01       38 阅读

最近更新

  1. TCP协议是安全的吗?

    2023-12-17 19:30:01       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2023-12-17 19:30:01       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2023-12-17 19:30:01       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2023-12-17 19:30:01       20 阅读

热门阅读

  1. 【Linux应用编程笔记】GPIO

    2023-12-17 19:30:01       33 阅读
  2. 网线制作方法及注意事项

    2023-12-17 19:30:01       39 阅读
  3. vue 中 watch 、computed、 watchEffect 区别

    2023-12-17 19:30:01       39 阅读
  4. 如何看待【前端】已死论?

    2023-12-17 19:30:01       37 阅读
  5. 线程Thread源代码思想学习1

    2023-12-17 19:30:01       36 阅读
  6. mysql查询-DQL查询语法-执行顺序--黑马程序员笔记

    2023-12-17 19:30:01       30 阅读
  7. 【Linux】项目自动化构建工具 - make/Makefile

    2023-12-17 19:30:01       40 阅读
  8. PAT乙级1017 A除以B

    2023-12-17 19:30:01       41 阅读
  9. python310_d.lib导致无法解析的外部符号的异常

    2023-12-17 19:30:01       59 阅读
  10. weston 1: 编译与运行傻瓜教程(补充)

    2023-12-17 19:30:01       33 阅读