我记得许多web组件教程都说connectedCallback
非常适合连接DOM事件或获取一些DOM元素(比如这个)。但我无法在lightelement:中运行一个简单的程序
import { LitElement, html } from 'lit-element';
class MyElement extends LitElement {
render() {
return html`<p id="root">template content</p>`;
}
connectedCallback() {
super.connectedCallback();
this.shadowRoot.getElementById('root'); // null
}
firstUpdated() {
this.shadowRoot.getElementById('root'); // not null
}
}
看起来它只在firstUpdated
中工作,firstUpdate
不是在第一次渲染后激发的吗?如果我需要在第一次渲染之前设置一些事件,该怎么办?为什么connectedCallback
在这里不起作用?
connectedCallback
按照规范工作,只是没有达到预期效果。
这些回调在的不同时刻触发
<my-element myattribute="foo"> 1. -> connectedCallback
<p id="root">
template content
</p>
</my-element> 2. -> firstUpdated (LitElement)
1. -> connectedCallback
表示元素被注入到DOM中。但其子项尚未被解析。
除非您使用FireFox(2021之前的版本!!),它在2时触发connectedCallback
太晚了。(已确认错误)
把元素想象成水管连接意味着软管连接到水龙头,而不是水流过水龙头。因此,您可以访问connectedCallback
中的数据属性(软管的属性)
这就是为什么connectedCallback
在这个1. ->
时刻发射。。。您可能需要基于其属性的内容。而且您不想等待所有内容都被解析(这可能是一个非常非常大的DOM树)
另请注意,每次移动DOM 中的元素时,connectedCallback
都会运行
如果你深入研究,你还会注意到attributeChangedCallback
在connectedCallback
之前运行,如果你的元素上有observerAttributes的话。
LitElement生命周期回调是糖,它们"保护"您免受(强大的)裸机Web组件行为的影响。
因此,没有LitElement,你可以做:
connectedCallback(){
// 1. -> do stuff
setTimeout(() => {//no tricks, just wait till that dreaded JS Event Loop is done
// all children are parsed
// 2. -> do stuff
});
}
有关血腥回调的详细信息,请参阅:等待connectedCallback:FireFox和Chromium差异中的元素升级
我在Lit 2.5中使用带有@query()-decorator的属性时遇到了类似的问题。
有一个方便的promise(this.updateComplete
),可以用来等待dom更新。
@query("#checkbox")
_input! : HTMLInputElement;
async connectedCallback() {
super.connectedCallback();
await this.updateComplete;
this._input.checked = this.checked;
}
这也适用于其他场景,例如,更改一个使某些内容在DOM中可见的属性,然后需要用相同的方法访问该元素。
@query("#checkbox")
_input! : HTMLInputElement;
_showMyElement() {
this.showCheckbox = true;
// wait for the DOM to update
await this.updateComplete;
// grab the element
this._input.checked = this.checked;
}