CustomHTMLElement构造函数执行顺序存疑,请求澄清生命周期逻辑
自定义HTML元素构造函数执行顺序与预期不符的原因
你的代码定义了两个自定义元素ExForm和ExInput,并在HTML中嵌套使用:
class ExForm extends HTMLElement { constructor() { super(); console.log(`${this.getAttribute('name')} constructor ${performance.now()}`); } connectedCallback() { console.log(`${this.getAttribute('name')} connected ${performance.now()}`); } } customElements.define("ex-form", ExForm); class ExInput extends HTMLElement { constructor() { super(); console.log(`${this.getAttribute('name')} constructor ${performance.now()}`); } connectedCallback() { console.log(`${this.getAttribute('name')} connected ${performance.now()}`); } } customElements.define("ex-input", ExInput);
HTML结构:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <ex-form name="form1"> <ex-input name="input1" ></ex-input> </ex-form> <ex-form name="form2"> <ex-input name="input2"></ex-input> </ex-form> </body> <script src="./index.js"></script> </html>
你预期构造函数执行顺序为form1 → input1 → form2 → input2,但实际是form1 → form2 → input1 → input2,核心原因是自定义元素的升级机制和脚本加载时机:
初始解析阶段:未知元素不触发构造函数
浏览器从上到下解析HTML时,底部的脚本还未执行,ExForm和ExInput还未被定义,所以<ex-form>和<ex-input>会被当作HTMLUnknownElement处理,此时不会调用自定义元素的构造函数。升级阶段:广度优先遍历DOM
脚本执行完成、自定义元素定义后,浏览器会自动升级DOM中已存在的未知元素。这个升级过程采用广度优先遍历:先处理所有顶层的自定义元素(form1、form2),再处理它们的子元素(input1、input2),因此构造函数的调用顺序符合你看到的结果。实现预期顺序的方法
若要让构造函数按DOM嵌套的深度优先顺序执行,只需将脚本移至<head>标签内。这样浏览器解析到自定义元素标签时,对应的类已经定义,会在解析过程中即时创建实例,遵循深度优先的解析顺序,最终执行顺序就会符合你的预期。
内容的提问来源于stack exchange,提问作者Dario
相关产品推荐
相关产品推荐

