connectedCallback中的发光元素getElementById返回null



我记得许多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都会运行

如果你深入研究,你还会注意到attributeChangedCallbackconnectedCallback之前运行,如果你的元素上有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;
}

最新更新