我正在尝试将 React 组件重建为 WebComponent 以消除对 React 的依赖。
我想要一个在 HTML 中看起来像这样的 WebComponent:
<editable-h1>Hello, world</editable-h1>
它应该像这样渲染:
<span>
<h1>Hello, world</h1>
<button onClick=this.onEdit>Edit</button>
</span>
如果我点击编辑按钮,我想让它呈现如下:
<form>
<input type='text' value='Hello, world'></input>
<button onClick=this.onSave>Save</button>
</form>
单击保存按钮通过 API 调用将更改保存到数据库,并将渲染返回到原始渲染(但带有编辑后的文本)。
我有信心我可以处理切换渲染和进行 API 调用,但我感到困惑的是如何从初始 WebComponent 中获取子元素文本“Hello,world”以进行渲染。
connectedCallback
触发开始标签<editable-h1>
所以你的
Hello World
还没有被解析
要等到解析完成,请使用
setTimeout
注意:所有为您提供
parsedCallback
的工具和库都会在幕后执行类似的技巧,使用 requestAnimationFrame
或 MutationObserver
(以及更多代码行)。
如果您认为单行
setTimeout
是hack;或者你不想用 setTimeout
松开那些 3 milliseconds,查看 Andrea Giammarchi 他的 html-parsed-element 代码
跟随 WC 大师,这个讨论一直在继续:
当孩子改变或解析器完成解析孩子时需要回调
https://github.com/WICG/webcomponents/issues/809
所有方法归结为相同的:等到 EventLoop 为空
事件循环到底是什么鬼? https://www.youtube.com/watch?v=8aGhZQkoFbQ
customElements.define("editable-h1", class extends HTMLElement {
connectedCallback() {
setTimeout(() => {
this.innerHTML = `<span>
<h1>Hello, world</h1>
<button>Edit</button>
</span>`;
this.h1 = this.querySelector("h1");
this.button = this.querySelector("button");
this.button.onclick = (evt) => this.onEdit(evt);
});
}
onEdit(evt) {
if (this.h1.isContentEditable) {
this.button.innerHTML = "edit";
this.h1.contentEditable = false;
} else {
this.button.innerHTML = "save";
this.h1.contentEditable = true;
this.h1.focus();
}
}
});
<editable-h1>Hello, world</editable-h1>