2 回答

TA貢獻1873條經驗 獲得超9個贊
你正陷入多個陷阱,就像每個人在他們的第一次組件冒險中一樣。
自定義元素(嚴格來說只有帶有shadowDOM 的元素才是 Web 組件)具有生命周期階段和回調。
你想在階段添加 DOM 內容constructor
;但是這個階段還沒有 DOM 元素。
只有在里面connectedCallback
才能添加DOM內容。
有了shadowDOM 就另當別論了,它的“DocumentFragment”在 中可用constructor
,你可以設置內容,但它還不是DOM元素!告訴connectedCallback
您自定義元素何時附加到 DOM。模板內容是一個 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()
}

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>
這樣,你有更多的開銷,但組件是真正封裝的。
添加回答
舉報