成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

一文讀懂Web Component

開發 前端
Shadow DOM。 主要用于將 Shadow DOM 的內容與外層 document DOM 隔離,可以理解為在document中的一個子容器,放置各種組件;HTML 模板。 使用 <template> 來定義組件模板,使用 <slot> 作為插槽使用(Vuer一定不陌生)。

前言

由于最近作者在學習微前端,web component也是其中一大特性,部分微前端框架使用到,也是深入學習了一下相關的知識,分享出來。

Web Component是什么?

Web Component 實際上一系列技術的組合,主要包含 3 部分:

  • 自定義元素。 在 HTML 基礎標簽外擴展自定義標簽元素,也就是我們平時使用框架的"組件";
  • Shadow DOM。 主要用于將 Shadow DOM 的內容與外層 document DOM 隔離,可以理解為在document中的一個子容器,放置各種組件;
  • HTML 模板。 使用 <template> 來定義組件模板,使用 <slot> 作為插槽使用(Vuer一定不陌生);

在一份html文件中的一個web component看起來是這樣的:

<trace-ele name="webComponent" version="0.0.1" desc="原生態自帶隔離的組件"" data-textnode-index-1701072719744="25" data-index-1701072719744="405" data-index-len-1701072719744="405" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>
  <div slot="slot-ele"" data-textnode-index-1701072719744="28" data-index-1701072719744="428" data-index-len-1701072719744="428" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>插槽內容</div" data-textnode-index-1701072719744="29" data-index-1701072719744="438" data-index-len-1701072719744="438" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>
</trace-ele" data-textnode-index-1701072719744="31" data-index-1701072719744="450" data-index-len-1701072719744="450" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>

看起來很像Vue吧?接下來讓我們一個個demo學習web component。

上手

由于Web Component親和原生,因此無需其他包的依賴,一個index.html和一個index.js即可體驗學習。

我們直接寫一個html模板,文章的案例組件統稱為<trace-ele />

index.html:

<body" data-textnode-index-1701072719744="48" data-index-1701072719744="606" data-index-len-1701072719744="606" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>
 <template id="trace"" data-textnode-index-1701072719744="56" data-index-1701072719744="628" data-index-len-1701072719744="628" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>
      <div class="container"" data-textnode-index-1701072719744="64" data-index-1701072719744="657" data-index-len-1701072719744="657" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>
        <img
          class="image"
          src="https://pic1.zhimg.com/50/v2-a6d65e05ec8db74369f3a7c0073a227a_200x0.webp"
          alt=""
        /" data-textnode-index-1701072719744="80" data-index-1701072719744="806" data-index-len-1701072719744="806" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>
        <p class="title"" data-textnode-index-1701072719744="88" data-index-1701072719744="831" data-index-len-1701072719744="831" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>學習Web Component</p" data-textnode-index-1701072719744="92" data-index-1701072719744="850" data-index-len-1701072719744="850" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>
        <p class="desc"" data-textnode-index-1701072719744="100" data-index-1701072719744="874" data-index-len-1701072719744="874" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>Web Component是微前端沙盒隔離原理的重要知識</p" data-textnode-index-1701072719744="104" data-index-1701072719744="906" data-index-len-1701072719744="906" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>
        <p class="price"" data-textnode-index-1701072719744="112" data-index-1701072719744="931" data-index-len-1701072719744="931" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>¥25.00</p" data-textnode-index-1701072719744="116" data-index-1701072719744="941" data-index-len-1701072719744="941" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>
      </div" data-textnode-index-1701072719744="120" data-index-1701072719744="953" data-index-len-1701072719744="953" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>
    </template" data-textnode-index-1701072719744="124" data-index-1701072719744="968" data-index-len-1701072719744="968" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>
    <trace-ele /" data-textnode-index-1701072719744="128" data-index-1701072719744="985" data-index-len-1701072719744="985" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>
    <script src="./index.js" /" data-textnode-index-1701072719744="136" data-index-1701072719744="1016" data-index-len-1701072719744="1016" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>
</body" data-textnode-index-1701072719744="139" data-index-1701072719744="1023" data-index-len-1701072719744="1023" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>

這里我們寫了一個"模板"——template,并在下面聲明了<trace-ele />組件。

而實現這一切的原理在index.js中。

class Trace extends HTMLElement {
  constructor() {
    super();
    const templateEle = document.getElementById("trace");
    const cloneEle = templateEle.content.cloneNode(true);
    this.appendChild(cloneEle);
  }
}

customElements.define("trace-ele", Trace);

Web Component組件本質是一個類繼承于HTMLElement,當customElements.define聲明完組件后,類中的this指向于組件本身,打印結果如下:

圖片圖片

在初始化時,需要提供給組件一個空殼,并且綁定template元素的id,這樣就出現組件效果了。

圖片圖片

看到這里是不是感覺和Vue很像呢?接下來我們繼續升級組件的功能~

來點樣式吧

在上一節基礎上,給組件上點樣式,很簡單,改變index.html即可,在template中加入style:

<body" data-textnode-index-1701072719744="209" data-index-1701072719744="1590" data-index-len-1701072719744="1590" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>
 <template id="trace"" data-textnode-index-1701072719744="217" data-index-1701072719744="1612" data-index-len-1701072719744="1612" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>
      <div class="container"" data-textnode-index-1701072719744="225" data-index-1701072719744="1641" data-index-len-1701072719744="1641" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>
        <img
          class="image"
          src="https://pic1.zhimg.com/50/v2-a6d65e05ec8db74369f3a7c0073a227a_200x0.webp"
          alt=""
        /" data-textnode-index-1701072719744="241" data-index-1701072719744="1790" data-index-len-1701072719744="1790" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>
        <p class="title"" data-textnode-index-1701072719744="249" data-index-1701072719744="1815" data-index-len-1701072719744="1815" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>學習Web Component</p" data-textnode-index-1701072719744="253" data-index-1701072719744="1834" data-index-len-1701072719744="1834" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>
        <p class="desc"" data-textnode-index-1701072719744="261" data-index-1701072719744="1858" data-index-len-1701072719744="1858" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>Web Component是微前端沙盒隔離原理的重要知識</p" data-textnode-index-1701072719744="265" data-index-1701072719744="1890" data-index-len-1701072719744="1890" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>
        <p class="price"" data-textnode-index-1701072719744="273" data-index-1701072719744="1915" data-index-len-1701072719744="1915" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>¥25.00</p" data-textnode-index-1701072719744="277" data-index-1701072719744="1925" data-index-len-1701072719744="1925" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>
      </div" data-textnode-index-1701072719744="281" data-index-1701072719744="1937" data-index-len-1701072719744="1937" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>
      
      <style" data-textnode-index-1701072719744="286" data-index-1701072719744="1956" data-index-len-1701072719744="1956" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>
        .container {
          display: inline-flex;
          flex-direction: column;
          border-radius: 6px;
          border: 1px solid silver;
          padding: 16px;
          margin-right: 16px;
        }
        .image {
          border-radius: 6px;
        }
        .title {
          font-weight: 500;
          font-size: 16px;
          line-height: 22px;
          color: #222;
          margin-top: 14px;
          margin-bottom: 9px;
        }
        .desc {
          margin-bottom: 12px;
          line-height: 1;
          font-size: 14px;
        }
        .price {
          font-size: 14px;
        }
      </style" data-textnode-index-1701072719744="391" data-index-1701072719744="2574" data-index-len-1701072719744="2574" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>
    </template" data-textnode-index-1701072719744="395" data-index-1701072719744="2589" data-index-len-1701072719744="2589" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>
    <trace-ele /" data-textnode-index-1701072719744="399" data-index-1701072719744="2606" data-index-len-1701072719744="2606" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>
    <script src="./index.js" /" data-textnode-index-1701072719744="407" data-index-1701072719744="2637" data-index-len-1701072719744="2637" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>
</body" data-textnode-index-1701072719744="410" data-index-1701072719744="2644" data-index-len-1701072719744="2644" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>

樣式生效:

圖片圖片

但是這里如果給一個通用標簽的樣式,就像這樣:

<body" data-textnode-index-1701072719744="416" data-index-1701072719744="2686" data-index-len-1701072719744="2686" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>
    <p" data-textnode-index-1701072719744="420" data-index-1701072719744="2693" data-index-len-1701072719744="2693" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>組件外的P標簽</p" data-textnode-index-1701072719744="424" data-index-1701072719744="2704" data-index-len-1701072719744="2704" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>
        <template" data-textnode-index-1701072719744="428" data-index-1701072719744="2722" data-index-len-1701072719744="2722" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>
        <p" data-textnode-index-1701072719744="432" data-index-1701072719744="2733" data-index-len-1701072719744="2733" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>組件中的P標簽</p" data-textnode-index-1701072719744="436" data-index-1701072719744="2744" data-index-len-1701072719744="2744" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>
        <style" data-textnode-index-1701072719744="440" data-index-1701072719744="2759" data-index-len-1701072719744="2759" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>
           p {
             color: red;
           }
            ...
            .container {}
        </style" data-textnode-index-1701072719744="455" data-index-1701072719744="2865" data-index-len-1701072719744="2865" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>
        </template" data-textnode-index-1701072719744="459" data-index-1701072719744="2884" data-index-len-1701072719744="2884" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>
</body" data-textnode-index-1701072719744="462" data-index-1701072719744="2891" data-index-len-1701072719744="2891" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>

效果如下:

圖片圖片

可以看到組件外的p標簽也被影響了,顏色變為紅色,而在組件概念中這個樣式其實只期望作用于組件本身。這也是樣式隔離的概念,而很幸運,Web Component提供了開箱即用的樣式隔離方案。

為了不讓 <template> 里的 <style> CSS 和全局的 CSS 有沖突,我們可以將組件掛在到 Shadow Root 上,再用 Shadow Root 掛到外層的 document DOM 上,這樣就可以實現 CSS 的隔離啦:

class Trace extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({ mode: "open" });
    
    const templateEle = document.getElementById("trace");
    const cloneEle = templateEle.content.cloneNode(true);

    this.shadowRoot.appendChild(cloneEle);
  }
}

customElements.define("trace-ele", Trace);

從控制臺中觀察:

圖片圖片

而如果有多個組件本質其實就是在document中有多個Shadow Root。

整個DOM架構圖是這樣的:

圖片圖片

Shadow DOM 的一大優點是能將 DOM 結構、樣式、行為與 Document DOM 隔離開,非常適合做組件的封裝,因此它能成為 Web Component 的重要組成部分之一。

Props

與Vue、React一樣,Web Component也提供了父傳子的形式。

index.html:

<trace-ele name="webComponent" version="0.0.1" desc="原生態自帶隔離的組件"" data-textnode-index-1701072719744="551" data-index-1701072719744="3716" data-index-len-1701072719744="3716" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>

這里傳了3個props給組件,在組件中打印this如下:

火眼金睛的我已經找到了在組件中接受傳參的入口:

圖片圖片

做一個簡單的動態賦值:

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

    this.attachShadow({ mode: "open" });

    const templateEle = document.getElementById("trace");
    const cloneEle = templateEle.content.cloneNode(true);
    cloneEle.querySelector('.container " data-textnode-index-1701072719744="593" data-index-1701072719744="4043" data-index-len-1701072719744="4043" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">> .title').textContent = this.getAttribute('name');
    cloneEle.querySelector('.container " data-textnode-index-1701072719744="600" data-index-1701072719744="4133" data-index-len-1701072719744="4133" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">> .price').textContent = this.getAttribute('version');
    cloneEle.querySelector('.container " data-textnode-index-1701072719744="607" data-index-1701072719744="4226" data-index-len-1701072719744="4226" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">> .desc').textContent = this.getAttribute('desc');

    this.shadowRoot.appendChild(cloneEle);
  }
}

customElements.define("trace-ele", Trace);

搞定~

Slot

HTML 模板的另一個好處是可以像 Vue 一樣使用 <slot>。比如,現在我們可以在這個 <trace-ele> 最下面添加一個插槽:

<body" data-textnode-index-1701072719744="632" data-index-1701072719744="4445" data-index-len-1701072719744="4445" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>
    <template id="trace"" data-textnode-index-1701072719744="640" data-index-1701072719744="4470" data-index-len-1701072719744="4470" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>
        <div class="container"" data-textnode-index-1701072719744="648" data-index-1701072719744="4501" data-index-len-1701072719744="4501" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>
            <p" data-textnode-index-1701072719744="652" data-index-1701072719744="4516" data-index-len-1701072719744="4516" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>組件中的P標簽</p" data-textnode-index-1701072719744="656" data-index-1701072719744="4527" data-index-len-1701072719744="4527" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>
            <img
              class="image"
              src="https://pic1.zhimg.com/50/v2-a6d65e05ec8db74369f3a7c0073a227a_200x0.webp"
              alt=""
            /" data-textnode-index-1701072719744="672" data-index-1701072719744="4696" data-index-len-1701072719744="4696" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>
            <p class="title"" data-textnode-index-1701072719744="680" data-index-1701072719744="4725" data-index-len-1701072719744="4725" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>學習Web Component</p" data-textnode-index-1701072719744="684" data-index-1701072719744="4744" data-index-len-1701072719744="4744" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>
            <p class="desc"" data-textnode-index-1701072719744="692" data-index-1701072719744="4772" data-index-len-1701072719744="4772" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>Web Component是微前端沙盒隔離原理的重要知識</p" data-textnode-index-1701072719744="696" data-index-1701072719744="4804" data-index-len-1701072719744="4804" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>
            <p class="price"" data-textnode-index-1701072719744="704" data-index-1701072719744="4833" data-index-len-1701072719744="4833" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>¥25.00</p" data-textnode-index-1701072719744="708" data-index-1701072719744="4843" data-index-len-1701072719744="4843" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>
            <slot name="slot-ele"" data-textnode-index-1701072719744="716" data-index-1701072719744="4877" data-index-len-1701072719744="4877" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">></slot" data-textnode-index-1701072719744="719" data-index-1701072719744="4884" data-index-len-1701072719744="4884" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>
        </div" data-textnode-index-1701072719744="723" data-index-1701072719744="4898" data-index-len-1701072719744="4898" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>
        <style" data-textnode-index-1701072719744="727" data-index-1701072719744="4913" data-index-len-1701072719744="4913" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>
        ...
        </style" data-textnode-index-1701072719744="732" data-index-1701072719744="4940" data-index-len-1701072719744="4940" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>
    </template" data-textnode-index-1701072719744="736" data-index-1701072719744="4955" data-index-len-1701072719744="4955" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>
    <trace-ele name="webComponent" version="0.0.1" desc="原生態自帶隔離的組件"" data-textnode-index-1701072719744="752" data-index-1701072719744="5024" data-index-len-1701072719744="5024" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>
        <div slot="slot-ele"" data-textnode-index-1701072719744="760" data-index-1701072719744="5053" data-index-len-1701072719744="5053" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>插槽內容</div" data-textnode-index-1701072719744="764" data-index-1701072719744="5063" data-index-len-1701072719744="5063" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>
    </trace-ele" data-textnode-index-1701072719744="768" data-index-1701072719744="5079" data-index-len-1701072719744="5079" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>
</body" data-textnode-index-1701072719744="771" data-index-1701072719744="5086" data-index-len-1701072719744="5086" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">>

這樣我們就可以實現自定義插槽內容了。

事件綁定

Web Component也可以給組件中元素或者插槽綁定事件。

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

    this.attachShadow({ mode: "open" });

    const templateEle = document.getElementById("trace");
    const cloneEle = templateEle.content.cloneNode(true);
    cloneEle
      .querySelector(".container " data-textnode-index-1701072719744="812" data-index-1701072719744="5401" data-index-len-1701072719744="5401" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">> .title")
      .addEventListener("click", this.onClick);

    this.shadowRoot.appendChild(cloneEle);
  }

  onClick = () =" data-textnode-index-1701072719744="825" data-index-1701072719744="5519" data-index-len-1701072719744="5519" class="" style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; display: inline-block; text-indent: initial;">> {
    alert("Click Me!");
  };
}

customElements.define("trace-ele", Trace);

圖片圖片

總結

上面主要給大家分享了一下 Web Component 的一些使用方法。總的來說,Web Component 是一系列 API 的組合:

  • Custom Element:注冊和使用組件
  • Shadow DOM:隔離 CSS
  • HTML template 和 slot:靈活的 DOM 結構

它看起來仿佛是現在主流框架的基建實現,框架也正是基于原生的能力實現出一整套的解決方案,就比如Vue的響應式以來追蹤、模板語法數據綁定,都是我們希望看到的。

責任編輯:武曉燕 來源: 量子前端
相關推薦

2023-12-22 19:59:15

2021-08-04 16:06:45

DataOps智領云

2023-05-20 17:58:31

低代碼軟件

2022-07-05 06:30:54

云網絡網絡云原生

2022-12-01 17:23:45

2022-10-20 08:01:23

2021-12-29 18:00:19

無損網絡網絡通信網絡

2022-07-26 00:00:03

語言模型人工智能

2018-09-28 14:06:25

前端緩存后端

2022-09-22 09:00:46

CSS單位

2022-11-06 21:14:02

數據驅動架構數據

2025-04-03 10:56:47

2023-08-01 19:11:05

瀏覽器本地存儲

2019-06-13 21:31:19

AI

2019-08-23 12:12:49

MQ消息隊列

2021-09-04 19:04:14

配置LogbackJava

2021-04-06 11:03:12

加密貨幣比特幣貨幣

2024-08-09 12:44:45

JavaScript原型鏈鏈條

2021-12-16 14:45:09

https架構服務端

2025-01-24 14:38:51

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 三级在线免费 | 欧美日韩亚洲成人 | 伊人久久综合 | 久久久久久国产精品 | 一区二区三区国产 | 国产精品日韩欧美一区二区三区 | 91精品在线观看入口 | 日日干夜夜草 | 日本不卡免费新一二三区 | 免费能直接在线观看黄的视频 | 日韩一区二区三区在线观看视频 | 国产精品国产精品国产专区不卡 | 99精品久久久 | 欧美一区二区 | 国产一区 | 日韩电影在线 | 久久久精品一区 | 91视频88av | 全免费a级毛片免费看视频免费下 | caoporn免费在线视频 | 国产亚洲一区二区三区在线观看 | 久久久久久国产 | 久久人| 一区二区三区电影网 | 午夜一区二区三区视频 | 亚洲视频一区 | 特黄特色大片免费视频观看 | 国产高清亚洲 | 人人干人人干人人干 | 久久99精品国产 | 日韩欧美中文字幕在线视频 | 成人av一区二区在线观看 | 亚洲视频免费观看 | 国内自拍视频在线观看 | 久久99深爱久久99精品 | 精品中文字幕一区 | 国产精品夜间视频香蕉 | 韩国理论电影在线 | 91精品国产乱码久久久久久久久 | 91久久视频 | 2021天天躁夜夜看 |