Skip to content

WebComponent

Web Components | MDN

  1. window.customElements 是一个 CustomElementRegistry 对象, 所以可以使用 define 方法

  2. HTMLElement 是继承 Element 所以可以使用 attachShadow 方法

html
<!DOCTYPE html>
<html lang="zh-cn">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="referrer" content="no-referrer" />
    <title>JavaScript</title>
  </head>
  <body>
    <div id="app"></div>
    <!-- javascript -->
    <script type="module" src="./index.js"></script>
  </body>
</html>
javascript
"use strict";

// 自定义一个 my-title 标签
window.customElements.define(
  "my-title",
  class extends HTMLElement {
    constructor() {
      super();
      this.init();
    }

    init() {
      const shadowRoot = this.attachShadow({ mode: "open" });
      shadowRoot.append(this.createDom());
    }

    createDom() {
      const title = this.textContent;
      const subTitle = this.getAttribute("sub-title");
      const h2 = document.createElement("h2");
      h2.style = "border-bottom: 1px solid #eee; font-size: 20px;";
      h2.textContent = title;
      if (subTitle) {
        const small = document.createElement("small");
        small.textContent = subTitle;
        small.style = "margin-left: 10px;color: #888; font-size: 12px;";
        h2.append(small);
      }
      return h2;
    }
  }
);

const app = document.querySelector("#app");

// 使用自定义标签 my-title
app.innerHTML = `<my-title sub-title="天弃之子">第1章: 诞生</my-title>
<my-title>第2章: 风雨欲来</my-title>
<my-title sub-title="大结局">第3章: 我命由我不由天</my-title>`;

template 标签

<template>:内容模板元素 - MDN

html
<!DOCTYPE html>
<html lang="zh-cn">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="referrer" content="no-referrer" />
    <title>JavaScript</title>
  </head>
  <body>
    <!-- 定义 my-title -->
    <template id="my-title-wrapper">
      <style>
        .title {
          font-size: 20px;
          border-bottom: 1px solid #eee;
          display: flex;
          align-items: center;
        }
        .sub-title {
          color: #888;
          font-size: 12px;
          margin-left: 10px;
        }
      </style>
      <h2 class="title">
        <slot name="title"></slot>
        <small class="sub-title">
          <slot name="subTitle"></slot>
        </small>
      </h2>
    </template>

    <!-- 使用 my-title -->
    <div id="app"></div>
    <script type="module" src="./index.js"></script>
  </body>
</html>
javascript
"use strict";
class MyTitle extends HTMLElement {
  constructor() {
    super();
    const shadowRoot = this.attachShadow({ mode: "open" });
    shadowRoot.append(this.createDom());
  }
  createDom() {
    const wrapper = document.querySelector("#my-title-wrapper");
    const tpl = wrapper.content;
    return tpl.cloneNode(true);
  }
}

// 定义 my-title
window.customElements.define("my-title", MyTitle);

// 使用
const app = document.querySelector("#app");
app.innerHTML = `
<my-title>
  <p slot="title">第1章: 诞生</p>
  <span slot="subTitle">天弃之子</span>
</my-title>
<my-title>
  <span slot="title">第2章: 风雨欲来</span>
</my-title>
<my-title sub-title="大结局">
  <p slot="title">第3章: 我命由我不由天</p>
  <a slot="subTitle" href="https://cn.bing.com/search?q=%E6%88%91%E5%91%BD%E7%94%B1%E6%88%91%E4%B8%8D%E7%94%B1%E5%A4%A9" >大结局</a>
</my-title>`;

Released under the MIT License.