等待connectedCallback中的元素升级:FireFox和Chromium的区别 [英] wait for Element Upgrade in connectedCallback: FireFox and Chromium differences
问题描述
更新2021年3月
FireFox错误已修复,现在的行为与Chromium和Safari相同.
这意味着等待 connectedCallback
中的JS EventLoop为空(带有 setTimeout
或 requestAnimationFrame
)现在是唯一的跨浏览器方法
事件循环到底是什么?-菲利普·罗伯茨
插入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 the only cross-browser method
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:
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屋!