1 回答
TA贡献1794条经验 获得超7个赞
constructor
永远无法创建在中设置 DOM 内容的自定义元素document.createElement()
您将看到许多示例(包括我的示例),其中 DOM 内容是在构造函数中设置的。
这些元素永远无法创建document.createElement
说明(HTML DOM API):
当您使用时:
<todo-card content=FOO></todo-card>
该元素(从 HTMLElement 扩展)具有所有 HTML 接口(它在 HTML DOM 中),
您可以在构造函数中设置 innerHTML
但是,当你这样做时:
document.createElement("todo-card");
构造函数在没有 HTML 接口的情况下运行(元素可能与 DOM 无关),因此在构造函数
中设置 innerHTML会产生错误:
未捕获的 DOMException:无法构造“CustomElement”:结果不得有子项
来自https://html.spec.whatwg.org/multipage/custom-elements.html#custom-element-conformance:
该元素不得获得任何属性或子元素,因为这违反了使用 createElement 或 createElementNS 方法的消费者的期望。一般来说,工作应该尽可能推迟到 connectedCallback
shadowDOM 是一个 DOM
使用shadowDOM时,您可以在构造函数中设置shadowDOM内容:
constructor(){
super().attachShadow({mode:"open"})
.innerHTML = `...`;
}
正确的代码(没有 shadowDOM):使用connectedCallback:
<todo-card content=FOO></todo-card>
<script>
window.customElements.define(
"todo-card",
class extends HTMLElement {
constructor() {
super();
//this.innerHTML = this.getAttribute("content");
}
connectedCallback() {
this.innerHTML = this.getAttribute("content");
}
}
);
try {
const todo = document.createElement("todo-card");
todo.setAttribute("content", "BAR");
document.body.appendChild(todo);
} catch (e) {
console.error(e);
}
</script>
您还有另一个小问题:content
是默认属性,FireFox 不会停止警告您:
或者不使用 createElement
const todo = document.createElement("todo-card");
todo.setAttribute("content", "BAR");
document.body.appendChild(todo);
可以写成:
const html = `<todo-card content="BAR"></todo-card`;
document.body.insertAdjacentHTML("beforeend" , html);
可以connectedCallback运行多次!
当你四处移动 DOM 节点时:
<div id=DO_Learn>
<b>DO Learn: </b><todo-card todo="Custom Elements API"></todo-card>
</div>
<div id="DONT_Learn">
<b>DON'T Learn!!! </b><todo-card todo="React"></todo-card>
</div>
<script>
window.customElements.define(
"todo-card",
class extends HTMLElement {
connectedCallback() {
let txt = this.getAttribute("todo");
this.append(txt);// and appended again on DOM moves
console.log("qqmp connectedCallback\t", this.parentNode.id, this.innerHTML);
}
disconnectedCallback() {
console.log("disconnectedCallback\t", this.parentNode.id , this.innerHTML);
}
}
);
const LIT = document.createElement("todo-card");
LIT.setAttribute("todo", "Lit");
DO_Learn.append(LIT);
DONT_Learn.append(LIT);
</script>
LIT 的 connectedCallback 运行
移动 LIT 时
disconnectedCallback 运行(注意父级!元素已经在新位置)
LIT 的 connectedCallback 再次运行,再次
"Learn Lit"
追加
这取决于你的程序员你的组件/应用程序必须如何处理这个
Web 组件库
像 Lit、HyperHTML 和 Hybrids 这样的库实现了额外的回调来帮助解决所有这些问题。
我建议先学习自定义元素 API,否则你学习的是工具而不是技术。
有工具的傻瓜,仍然是傻瓜
添加回答
举报