2 回答

TA貢獻(xiàn)1873條經(jīng)驗(yàn) 獲得超9個(gè)贊
你正陷入多個(gè)陷阱,就像每個(gè)人在他們的第一次組件冒險(xiǎn)中一樣。
自定義元素(嚴(yán)格來說只有帶有shadowDOM 的元素才是 Web 組件)具有生命周期階段和回調(diào)。
你想在階段添加 DOM 內(nèi)容constructor
;但是這個(gè)階段還沒有 DOM 元素。
只有在里面connectedCallback
才能添加DOM內(nèi)容。
有了shadowDOM 就另當(dāng)別論了,它的“DocumentFragment”在 中可用constructor
,你可以設(shè)置內(nèi)容,但它還不是DOM元素!告訴connectedCallback
您自定義元素何時(shí)附加到 DOM。模板內(nèi)容是一個(gè) DocumentFragment,但您
.innerHTML
需要一個(gè)字符串。
由于(在您的使用中)<template>
?是一個(gè) DOM 元素,您可以閱讀它的 innerHTML(見下文)
所以,是的,沒有shadowDOM的自定義元素是可能的:
您將看到兩次<template>
內(nèi)容,演示了添加內(nèi)容的 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是您準(zhǔn)備元素的地方
這constructor也會在您執(zhí)行時(shí)運(yùn)行document.createElement("my-element")。
connectedCallback當(dāng)您的元素添加到 DOM 時(shí)運(yùn)行
如果您不指定方法,則運(yùn)行其 Class 父類中的方法,因此在上面的代碼中,constructor將執(zhí)行 HTMLElement 中的(默認(rèn))方法。
這就是為什么您需要super()在自己的constructor... 中執(zhí)行constructor來自 HTMLElement 的原因。
筆記:
constructor(){
?let template = document.getElementById("MY-ELEMENT").content.cloneNode(true);
?super().attachShadow({mode:"open").append(template);
}
是完全有效的代碼;說“超級需要先運(yùn)行”的谷歌文檔是錯(cuò)誤的。
您需要運(yùn)行才能訪問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
當(dāng)您的組件冒險(xiǎn)將涉及類繼承時(shí);
你調(diào)用父方法:
connectedCallback(){
? super.connectedCallback()
}

TA貢獻(xiàn)1864條經(jīng)驗(yàn) 獲得超6個(gè)贊
自定義元素最簡單的實(shí)現(xiàn)是:
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,而必須通過外部樣式表來為組件設(shè)置樣式。
使用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>
這樣,你有更多的開銷,但組件是真正封裝的。
添加回答
舉報(bào)