在 connectedCallback 中等待元素升级:FireFox 和 Chromium 的区别 [英] wait for Element Upgrade in connectedCallback: FireFox and Chromium differences
问题描述
2021 年 3 月更新:
修复了 FireFox 错误,现在其行为与 Chromium 和 Safari 相同.
这意味着在 connectedCallback
中等待 JS EventLoop 为空(使用 setTimeout
或 requestAnimationFrame
)现在是一个跨浏览器的方法
connectedCallback(){setTimeout(()=>{//可以在这里访问 lightDOM});//,0 不需要}
事件循环到底是什么?- 菲利普·罗伯茨
,确保插入 DOM 会立即触发 connectedCallback,而不是将回调反应放在备份元素队列上,让它在下一个微任务检查点被触发.这意味着当元素为零时,通常会调用 connectedCallback孩子,正如预期的那样,而不是随机数,这取决于什么时候看到下一个自定义元素.
我们可以得出结论,Firefox 也遵循规范...是的,但出于上述原因,我们不应依赖 connectedCallback
中的内容.
Update March 2021:
FireFox bug fixed, now behaves the same as Chromium and Safari.
That means waiting for the JS EventLoop to be empty (with setTimeout
or requestAnimationFrame
) in the connectedCallback
is now a cross-browser method
connectedCallback(){
setTimeout(()=>{
// can access lightDOM here
}); // ,0 not required
}
What the heck is the Event Loop? - Philip Roberts
https://www.youtube.com/watch?v=8aGhZQkoFbQ
Update Oct. 28 2020:
Now reported by Mozilla engineer Anne van Kesteren as a bug in FireFox:
FireFox invokes the connectedCallback too late:
https://bugzilla.mozilla.org/show_bug.cgi?id=1673811
First post May. 2020:
Bitten again by this Chrome Element upgrade issue, after spending a week in FireFox.
Forgot to wrap code in a setTimeout before delivering to Chromium browsers.
FireFox prints: ABCD
Chromium prints: ADCD
Question: Why the difference?
<script>
customElements.define('my-element', class extends HTMLElement {
connectedCallback() {
console.log(this.innerHTML);// "A" in FireFox, "" in other Browsers
if (this.innerHTML == "A")
this.innerHTML = this.innerHTML + "B";
else
setTimeout(() => this.innerHTML = this.innerHTML + "D");
}
})
</script>
<my-element>A</my-element><my-element>C</my-element>
Related answers over the past years:
Update #1
- Apple/Safari: prints: ADCD (same as Chromium)
note: Chromium Blink engine is a fork of Apples (WebKit)WebCore code!!
Update #2
With Supersharps reference we found the related threads:
(2016) connectedCallback timing when the document parser creates custom elements
https://github.com/w3c/webcomponents/issues/551(2019) Need a callback for when children changed or parser finished parsing children
https://github.com/w3c/webcomponents/issues/809
order of callbacks in FireFox versus Chromium:
source: https://jsfiddle.net/CustomElementsExamples/n20bwckt/
I think the Chrome/Safari behaviour is less intuitive for the beginners, but with some more complex scenarios (for example with child custom elements) then it is much more consistant.
See the different examples below. They act strangely in Firefox...
Another use case that I don't have the courage to code: when a document is parsed, maybe you don't have the end of the document yet. Therefore, when a custom element is created, you cannot be sure you get all its children until you get the closing tag (that could never arrive).
According to Ryosuke Niwa for WebKit:
The problem then is that the element won't get connectedCallback until all children are parsed. For example, if the entire document was a single custom element, that custom element would never receive connectedCallback until the entire document is fetched & parsed even though the element is really in the document. That would be bad.
So it's better no to wait and connect the custom element as soon as it is created, that means with no child.
<script>
customElements.define( 'c-e', class extends HTMLElement {} )
customElements.define('my-element', class extends HTMLElement {
connectedCallback() {
console.log(this.innerHTML, this.childNodes.length)
let span = document.createElement( 'span' )
if (this.innerHTML.indexOf( 'A' ) >= 0 )
span.textContent = 'B'
else
span.textContent = 'D'
setTimeout( () => this.appendChild( span ) )
}
})
</script>
<my-element>A</my-element><my-element>C</my-element>
<br>
<my-element><c-e></c-e>A</my-element><my-element>A<c-e></c-e></my-element>
<br>
<my-element><c-e2></c-e2>A</my-element><my-element>A<c-e2></c-e2></my-element>
As far as I understand, there was a consensus on it that led to adjust the spec that (Chrome/Safari) way:
Fixes w3c/webcomponents#551 by ensuring that insertions into the DOM trigger connectedCallback immediately, instead of putting the callback reaction on the the backup element queue and letting it get triggered at the next microtask checkpoint. This means connectedCallback will generally be invoked when the element has zero children, as expected, instead of a random number depending on when the next custom element is seen.
We can conclude that Firefox also follow the spec... yes, but we should not rely on the content in connectedCallback
for the reasons discussed above.
这篇关于在 connectedCallback 中等待元素升级:FireFox 和 Chromium 的区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!