最小重现 - js 代码部分,第 5 行。
class Bazooka extends HTMLElement {
host;
constructor() {
super();
this.className = "hi"; // why ?? see bullet number - 5 --> https://html.spec.whatwg.org/multipage/custom-elements.html#custom-element-conformance
this.host = this.attachShadow({ mode: "open" });
}
connectedCallback() {
let foo = document.querySelector(".test");
this.host.appendChild(foo.content);
}
}
customElements.define("bazooka-show", Bazooka);
<!DOCTYPE html>
<html lang="en">
<head>
<title>Home</title>
</head>
<body>
<main>
<bazooka-show></bazooka-show>
</main>
<template class="test">
<p>A shadow DOM.</p>
</template>
</body>
</html>
根据 html 规范 - https://html.spec.whatwg.org/multipage/custom-elements.html#custom-element-conformance 要点 - 5,
constructor()
不应该获得属性,对吗?
该元素不得获得任何属性或子元素
我的问题是 - 为什么自定义元素接受属性(className)?浏览器不应该抛出错误吗?
类的构造函数用于根据该类及其扩展的类实例化一个对象。在构造函数中,对象(this)被创建/已经存在。对象可以具有任何属性,因此在构造函数中设置
this.className
、this.id
或 this.foo
是完全可以的。直接回答你的问题:不,它不应该抛出错误。在对象上设置任何属性都可以。
恰好创建的对象继承自
HTMLElement
,并且它神奇地绑定到 DOM 元素,并且在这样做时,创建了与对象上的匹配属性关联的属性。
在示例中,我在构造函数中添加了更多属性。您可以看到 id 最终也作为一个属性。如果您尝试设置像
this.nodeName
这样的属性,您会发现收到错误,因为它是从 HTMLElement 继承的只读属性。
class Bazooka extends HTMLElement {
host;
constructor() {
super();
this.className = "hi";
this.id = "id01";
this.foo = "bar";
//this.nodeName = "error";
this.host = this.attachShadow({ mode: "open" });
}
connectedCallback() {
let foo = document.querySelector(".test");
this.host.appendChild(foo.content);
}
}
customElements.define("bazooka-show", Bazooka);
<!DOCTYPE html>
<html lang="en">
<head>
<title>Home</title>
</head>
<body>
<main>
<bazooka-show></bazooka-show>
</main>
<template class="test">
<p>A shadow DOM.</p>
</template>
</body>
</html>