Untitled

创建一个 my-info 自定义组件

通过 shadowDOM 创建

main.js

window.customElements.define(
  'my-info',
  class extends HTMLElement {
    constructor() {
      super();

      this.title = this.textContent;
      this.avatar = this.getAttribute('avatar');
      this.myName = this.getAttribute('name');
      this.age = this.getAttribute('age');

      this.init();
    }
    init() {
      // shadowRoot -> 形成了 shadowDOM
      
      // attachShadow 触发一个shadow
      const shadowDOM = this.attachShadow({ mode: 'open' });
      shadowDOM.appendChild(this.createDOM());
    }
    createDOM() {
      var oContainer = this.createContainer();
      oContainer.appendChild(this.createTitle());
      oContainer.appendChild(this.createAvatar());
      oContainer.appendChild(this.createName());
      oContainer.appendChild(this.createAge());
      return oContainer;
    }
    createContainer() {
      const oContainer = document.createElement('div');
      oContainer.className = 'my-info-container';
      return oContainer;
    }
    createTitle() {
      const oTitle = document.createElement('h1');
      oTitle.className = 'my-info-title';
      oTitle.textContent = this.title;
      return oTitle;
    }
    createAvatar() {
      const oAvatar = document.createElement('div');
      oAvatar.className = 'my-info-avatar';
      oAvatar.innerHTML = `<img style="width: 100px;" src="${this.avatar}" />`;
      return oAvatar;
    }
    createName() {
      const oName = document.createElement('p');
      oName.className = 'my-info-name';
      oName.textContent = `Name: ${this.myName}`;
      return oName;
    }
    createAge() {
      const oAge = document.createElement('p');
      oAge.className = 'my-info-age';
      oAge.textContent = `Age: ${this.age}`;
      return oAge;
    }
  }
)

public/index.html

<body>
  <div id="app">
  </div>
  <my-info
    avatar="<https://placekitten.com/100/100>"
    name='Lance',
    age="26"
  >
    I'm Lance
  </my-info>
  ...
</body>

Untitled

通过 template + slot 创建

public/index.html

<body>
  <div id="app">
  </div>
  <my-info
    avatar="<https://placekitten.com/100/100>"
    name='Lance',
    age="26"
  >
    I'm Lance
  </my-info>

  <template
    id="my-article-template">
    <style>
      h1 {
        color: red;
      }

      h1 .author,
      h1 .date-time {
        font-size: 16px;
        color: #666;
        font-weight: normal;
      }
    </style>
    <div class="my-article">
      <div class="my-article-title">
        <slot name="title" class="title"></slot>
        <slot name="author" class="author"></slot>
        <slot name="dateTime" class="date-time"></slot>
      </div>
      <p class="my-article-content">
        <slot name="content"></slot>
      </p>
    </div>
  </template>
  ...
</body>

写完后会发现在DOM中有,但界面上不显示:

Untitled

main.js

class MyArticle extends HTMLElement {
  constructor() {
    super();

    const _tpl = document.getElementById('my-article-template').content;
    const shadowDOM = this.attachShadow({ mode: 'open' });
    shadowDOM.appendChild(_tpl.cloneNode(true)); // cloneNode 传参为 true 会克隆其子元素;false则只克隆当前元素
  }
}

window.customElements.define('my-article', MyArticle);

public/index.html

<!DOCTYPE html>
<html lang="en">
<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">
  <title>Document</title>
</head>
<body>
  <div id="app">
  </div>

  <my-article>
    <p slot="title">This is my TITLE</p>
    <span slot="author">Lance</span>
    <span slot="dateTime">- 14:15</span>
    <p slot="content">
      This is my content
    </p>
  </my-article>

  <template
    id="my-article-template">
    <style>
      h1 {
        color: red;
      }

      h1 .author,
      h1 .date-time {
        font-size: 16px;
        color: #666;
        font-weight: normal;
      }
    </style>
    <div class="my-article">
      <div class="my-article-title">
        <slot name="title" class="title"></slot>
        <slot name="author" class="author"></slot>
        <slot name="dateTime" class="date-time"></slot>
      </div>
      <p class="my-article-content">
        <slot name="content"></slot>
      </p>
    </div>
  </template>
  <script src="<https://unpkg.com/[email protected]/dist/vue.js>"></script>
  <!-- <script src="<https://unpkg.com/[email protected]/dist/vue.global.js>"></script> -->
  <script src="<https://unpkg.com/[email protected]/dist/axios.min.js>"></script>
</body>
</html>

Untitled