在FireFox中呆了一个星期后,又被这个Chrome元素升级问题咬住了。
在交付给Chromium浏览器之前,忘了用setTimeout包裹代码。
FireFox打印。ABCD
铬版画。ADCD
问题。 如果FireFox能够表现出一个开发者所期望的样子。为什么呢? Chromium有什么不同吗?
<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>
过去几年的相关回答。
注:Chromiums Blink引擎是苹果公司的一个分叉点 (WebKit)WebCore 代码 所以,原因可能比Custom Elements更深层次(我们可以再次责怪苹果吗?
通过Supersharps参考,我们找到了相关的线程。
(2016)文档解析器创建自定义元素时的connectedCallback定时 https:/github.comw3cwebcomponentsissues551。
(2019年)需要一个回调,当孩子发生变化或解析器完成解析孩子时,需要回调。https:/github.comw3cwebcomponentsissues809。
我认为ChromeSafari的行为对于初学者来说不那么直观,但对于一些更复杂的场景(例如与子自定义元素),那么它就会更加一致。
请看下面的不同例子。它们在Firefox中的行为很奇怪......
另一个我没有勇气编写代码的用例:当一个文档被解析时,也许你还没有看到文档的结尾。因此,当一个自定义元素被创建时,你不能确定你得到了它的所有子元素,直到你得到结束标签(可能永远不会到达)。
根据Ryosuke Niwa for WebKit的说法。
那么问题就在于,元素不会得到connectedCallback,直到所有的子元素都被解析出来。例如,如果整个文档是一个单一的自定义元素,那么在整个文档被获取&解析之前,该自定义元素永远不会收到connectedCallback,即使该元素真的在文档中。这样就不好了。
所以最好不要等待,一旦创建了自定义元素,也就是在没有子元素的情况下,立即连接。
<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>
据我所知,大家对此达成了共识,所以才调整了规范(ChromeSafari)的方式。
修复 w3cwebcomponents#551 确保插入DOM的元素会立即触发connectCallback,而不是将回调反应放在备份元素队列中,让它在下一个微任务检查点被触发。这意味着connectCallback一般会像预期的那样,在元素的子代为零时被调用,而不是根据下一个自定义元素被看到时的随机数。
我们可以得出结论,Firefox也遵循了规范......是的,但我们不应该依赖在 connectedCallback
出于上述原因。