Skip to content

Web Component

官方解释

  • Web Component 是一套不同的技术,允许你创建可重用的定制元素(它们的功能封装在你的代码之外)并且在你的 web 应用中使用它们

Js 自定义标签

html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <my-info></my-info>
  </body>
  <script>
    class MyInfoTag extends HTMLElement {
      constructor() {
        super();

        var image = document.createElement("img");
        image.src =
          "https://gips1.baidu.com/it/u=1658389554,617110073&fm=3028&app=3028&f=JPEG&fmt=auto?w=1280&h=960";
        image.width = 40;
        image.classList.add("image");

        var container = document.createElement("div");
        container.classList.add("container");

        var name = document.createElement("p");
        name.classList.add("name");
        name.innerText = "Name: ZiJieYuan";

        var email = document.createElement("p");
        email.classList.add("email");
        email.innerText = "Email: ZiJieYuan@163.com";

        var button = document.createElement("button");
        button.classList.add("button");
        button.innerText = "Follow";

        container.append(name, email, button);
        this.append(image, container);
      }
    }
    window.customElements.define("my-info", MyInfoTag);
  </script>
</html>

<template>标签

  • 使用 JavaScript 写上一节的 DOM 结构很麻烦,Web Components API 提供了<template>标签,可以在它里面使用 HTML 定义 DOM
html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <my-info></my-info>

    <template id="my-info-template">
      <style>
        :host {
          display: flex;
          align-items: center;
          width: 450px;
          height: 180px;
          background-color: #d4d4d4;
          border: 1px solid #d5d5d5;
          box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.1);
          border-radius: 3px;
          overflow: hidden;
          padding: 10px;
          box-sizing: border-box;
          font-family: "Poppins", sans-serif;
        }
        .image {
          flex: 0 0 auto;
          width: 160px;
          height: 160px;
          vertical-align: middle;
          border-radius: 5px;
        }
        .container {
          box-sizing: border-box;
          padding: 20px;
          height: 160px;
        }
        .container > .name {
          font-size: 20px;
          font-weight: 600;
          line-height: 1;
          margin: 0;
          margin-bottom: 5px;
        }
        .container > .email {
          font-size: 12px;
          opacity: 0.75;
          line-height: 1;
          margin: 0;
          margin-bottom: 15px;
        }
        .container > .button {
          padding: 10px 25px;
          font-size: 12px;
          border-radius: 5px;
          text-transform: uppercase;
        }
      </style>
      <img
        src="https://gips1.baidu.com/it/u=1658389554,617110073&fm=3028&app=3028&f=JPEG&fmt=auto?w=1280&h=960"
        width="40"
        class="image"
      />
      <div class="container">
        <p class="name">Name: ZiJieYuan template</p>
        <p class="email">Email: ZiJieYuan_template@163.com</p>
        <button class="button">Follow</button>
      </div>
    </template>
  </body>
  <script>
    class MyInfo extends HTMLElement {
      constructor() {
        super();

        var templateElem = document.getElementById("my-info-template");
        var content = templateElem.content.cloneNode(true);

        //  :host CSS 伪类选择内部使用了该 CSS 的影子 DOM(shadow DOM) 的影子宿主(shadow host)——换句话说,这允许你从其影子 DOM 内部选择自定义元素
        // https://developer.mozilla.org/zh-CN/docs/Web/CSS/:host
        const shadowRoot = this.attachShadow({ mode: "open" });
        shadowRoot.appendChild(content);

        // 添加操作事件
        this.$button = shadowRoot.querySelector("button");
        this.$button.addEventListener("click", () => {
          alert("click");
        });
      }
    }

    window.customElements.define("my-info", MyInfo);
  </script>
</html>

参考文献

Released under the MIT License.