亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何在沒有 attachShadow 的情況下創建自定義元素?

如何在沒有 attachShadow 的情況下創建自定義元素?

小唯快跑啊 2023-06-15 16:47:41
假設我有這樣的代碼:class MyElem extends HTMLElement {  constructor() {    super();        let templateContent = document.getElementById('template-elem').content;    this.innerHTML = templateContent.cloneNode(true);  }}window.customElements.define('my-elem', MyElem);<template id="template-elem">  <div class="a">    <div class="b">b</div>    <div class="c">c</div>  </div></template><my-elem></my-elem>為什么這不起作用?在 Chrome 檢查器中,自定義元素內部沒有 HTML。我也試過這樣做:this.append(templateContent.cloneNode(true)); 但這也導致了一個空的 HTML 樹。所有教程都提到使用影子 DOM,如下所示:this.attachShadow({mode: 'open'}).appendChild(templateContent.cloneNode(true));雖然這有效,但它會強制您將 Shadow DOM 用于您的自定義元素。有沒有辦法在不需要使用 Shadow DOM 的情況下將模板的 HTML 附加到您的自定義元素?我更愿意在我的小用例中使用全局 CSS 樣式。
查看完整描述

2 回答

?
眼眸繁星

TA貢獻1873條經驗 獲得超9個贊

你正陷入多個陷阱,就像每個人在他們的第一次組件冒險中一樣。

  1. 自定義元素(嚴格來說只有帶有shadowDOM 的元素才是 Web 組件)具有生命周期階段和回調。
    你想在階段添加 DOM 內容constructor;但是這個階段還沒有 DOM 元素。
    只有在里面connectedCallback才能添加DOM內容。
    有了shadowDOM 就另當別論了,它的“DocumentFragment”在 中可用constructor,你可以設置內容,但它還不是DOM元素!告訴connectedCallback您自定義元素何時附加到 DOM。

  2. 模板內容是一個 DocumentFragment,但您.innerHTML需要一個字符串。
    由于(在您的使用中)<template>?一個 DOM 元素,您可以閱讀它的 innerHTML(見下文)


所以,是的,沒有shadowDOM的自定義元素是可能的:

您將看到兩次<template>內容,演示了添加內容的 2 種方式。

<script>

? customElements.define("my-element", class extends HTMLElement {

? ? connectedCallback() {

? ? ? let template = document.getElementById(this.nodeName);

? ? ? this.innerHTML = template.innerHTML;

? ? ? this.append(template.content.cloneNode(true))

? ? }

? })


</script>


<template id="MY-ELEMENT">

? Hello, I am an Element!

</template>


<my-element></my-element>

這constructor是您準備元素的地方


這constructor也會在您執行時運行document.createElement("my-element")。


connectedCallback當您的元素添加到 DOM 時運行


如果您不指定方法,則運行其 Class 父類中的方法,因此在上面的代碼中,constructor將執行 HTMLElement 中的(默認)方法。

這就是為什么您需要super()在自己的constructor... 中執行constructor來自 HTMLElement 的原因。


筆記:


constructor(){

?let template = document.getElementById("MY-ELEMENT").content.cloneNode(true);

?super().attachShadow({mode:"open").append(template);

}

是完全有效的代碼;說“超級需要先運行”的谷歌文檔是錯誤的。

您需要運行才能訪問super() 元素自己的范圍this


這就是為什么我更喜歡:


constructor(){


?// do anything you want here, but you can not use 'this'


?super() // Sets AND Returns 'this'

? ?.attachShadow({mode:"open") // both Sets AND Returns this.shadowRoot

? ?.append(document.getElementById(this.nodeName).content.cloneNode(true));

}

注意append()在 IE 中不可用;所以 oldskool 程序員不會知道它的多功能性:https://developer.mozilla.org/en-US/docs/Web/API/Element/append


當您的組件冒險將涉及類繼承時;

你調用父方法:


connectedCallback(){

? super.connectedCallback()

}


查看完整回答
反對 回復 2023-06-15
?
慕尼黑的夜晚無繁華

TA貢獻1864條經驗 獲得超6個贊

自定義元素最簡單的實現是:


class MyComponent extends HTMLElement {

    connectedCallback() {

        this.innerHTML = `<div>Hello world</div>`

    }

}


customElements.define('my-component', MyComponent)

my-component {

  display: block;

  border: 1px dotted #900

}

<my-component></my-component>


但是,如果不使用 Shadow DOM,則無法封裝 CSS,而必須通過外部樣式表來為組件設置樣式。


使用Shadow DOM編寫組件的最簡單方法如下所示:


class MyOtherComponent extends HTMLElement {

    constructor() {

        super()

        this.shadow = this.attachShadow({ mode: "open" })

    }


    connectedCallback() {

        this.shadow.innerHTML = `

            <style>

                :host {

                  display: block;

                  border: 1px dotted #900

                }

            </style>

            <div class="component">Hello World!</div>

        `

    }

}


customElements.define('my-other-component', MyOtherComponent)

<my-other-component></my-other-component>

這樣,你有更多的開銷,但組件是真正封裝的。



查看完整回答
反對 回復 2023-06-15
  • 2 回答
  • 0 關注
  • 151 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號