You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 22:35:18