了解 customElements 处理顺序
Understanding customElements processing order
有一个时间点,父自定义元素可以在子元素使用自定义方法之前访问它们。
class CustomParent extends HTMLElement {
connectedCallback() {
// works
this.children[0].textContent = "bar";
// works
setTimeout(() => this.children[0].test(), 0);
// throws a Type error
this.children[0].test();
}
}
customElements.define("custom-parent", CustomParent);
class CustomChild extends HTMLElement {
test() {
this.textContent = "baz";
}
}
customElements.define("custom-child", CustomChild);
document.body.innerHTML = `
<custom-parent>
<custom-child>foo</custom-child>
</custom-parent>
`;
这怎么可能,推迟 this.children[0].test()
安全吗?
这是由于 upgrading process 的自定义元素。
第一步:当你执行document.body.innerHTML = '<custom-parent><custom-child>foo</custom-child></custom-parent>'
时,2个元素作为未知元素.[=插入到页面中18=]
第二步:父元素先升级。它可以访问其子元素(然后更新其 textContent
属性)作为 unknown 元素。但是它无法访问访问自定义元素test()
方法...因为它还不是自定义元素!
第三步:子元素紧接着升级,现在得到一个test()
方法。
第 4 步:延迟的 test()
调用在逻辑上有效:-)
参见下面的示例。它使用 querySelectorAll( ':not(:defined)' )
表示子级在其父级之后升级。
class CustomParent extends HTMLElement {
constructor() { super() ; console.log( 'parent upgraded') }
connectedCallback() {
console.log( 'parent connected', this.children[0].outerHTML )
// works
this.children[0].textContent = 'bar'
// works
setTimeout( () => this.children[0].test() )
// throws a Type error
try {
this.children[0].test()
} catch ( e ) {
//this shows the parent is upgraded, but not its child
var not_upgraded = document.querySelectorAll( ':not(:defined)' )
console.log( 'not upgraded: ', ...not_upgraded )
}
}
}
customElements.define( 'custom-parent', CustomParent )
class CustomChild extends HTMLElement {
constructor() { super() ; console.log( 'child upgraded') }
test() { this.textContent = 'baz' }
}
customElements.define( 'custom-child', CustomChild )
document.body.innerHTML = `
<custom-parent>
<custom-child>foo</custom-child>
</custom-parent>`
有一个时间点,父自定义元素可以在子元素使用自定义方法之前访问它们。
class CustomParent extends HTMLElement {
connectedCallback() {
// works
this.children[0].textContent = "bar";
// works
setTimeout(() => this.children[0].test(), 0);
// throws a Type error
this.children[0].test();
}
}
customElements.define("custom-parent", CustomParent);
class CustomChild extends HTMLElement {
test() {
this.textContent = "baz";
}
}
customElements.define("custom-child", CustomChild);
document.body.innerHTML = `
<custom-parent>
<custom-child>foo</custom-child>
</custom-parent>
`;
这怎么可能,推迟 this.children[0].test()
安全吗?
这是由于 upgrading process 的自定义元素。
第一步:当你执行document.body.innerHTML = '<custom-parent><custom-child>foo</custom-child></custom-parent>'
时,2个元素作为未知元素.[=插入到页面中18=]
第二步:父元素先升级。它可以访问其子元素(然后更新其 textContent
属性)作为 unknown 元素。但是它无法访问访问自定义元素test()
方法...因为它还不是自定义元素!
第三步:子元素紧接着升级,现在得到一个test()
方法。
第 4 步:延迟的 test()
调用在逻辑上有效:-)
参见下面的示例。它使用 querySelectorAll( ':not(:defined)' )
表示子级在其父级之后升级。
class CustomParent extends HTMLElement {
constructor() { super() ; console.log( 'parent upgraded') }
connectedCallback() {
console.log( 'parent connected', this.children[0].outerHTML )
// works
this.children[0].textContent = 'bar'
// works
setTimeout( () => this.children[0].test() )
// throws a Type error
try {
this.children[0].test()
} catch ( e ) {
//this shows the parent is upgraded, but not its child
var not_upgraded = document.querySelectorAll( ':not(:defined)' )
console.log( 'not upgraded: ', ...not_upgraded )
}
}
}
customElements.define( 'custom-parent', CustomParent )
class CustomChild extends HTMLElement {
constructor() { super() ; console.log( 'child upgraded') }
test() { this.textContent = 'baz' }
}
customElements.define( 'custom-child', CustomChild )
document.body.innerHTML = `
<custom-parent>
<custom-child>foo</custom-child>
</custom-parent>`