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>
这样,你有更多的开销,但组件是真正封装的。
添加回答
举报