Javascript,误解CustomHTMLElement的生命周期:需要澄清

3

我目前正在学习CustomHtmlElements,并且我对构造函数调用的顺序有一些误解。

例如,如果我有两个CustomHtmlElements:

class ExForm extends HTMLElement {
  constructor() {
    super();
    console.log(`${this.getAttribute('name')} constructor ${performance.now()}`);
    //debugger;
  }
  
  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()}`);
    //debugger;
  }
  
   connectedCallback() {
    console.log(`${this.getAttribute('name')} connected ${performance.now()}`);
  }
}

customElements.define("ex-input", ExInput);
<!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元素呈现在页面上的顺序不一致吗?
1个回答

3

这取决于 Web 组件何时被定义。

在 StackOverflow 代码片段中,您的 JS 代码将在 DOM 解析运行,因此将升级现有的自定义元素(最初解析为HTMLUnknownElement

ex-form首先被定义,因此所有现有的<ex-form>将首先进行升级。
然后定义ex-input,接下来所有现有的<ex-input>都会进行升级。

(请参见下面的代码片段)如果您将声明放在DOM解析之前,则会得到您期望的顺序:

一般来说:不要依赖DOM中的顺序,因为你无法控制用户/开发者何时加载你的Web组件文件。
如果你需要检查依赖项,可以使用customElements.whenDefined()

<script>
  class BaseClass extends HTMLElement {
    constructor() {
      super();
      console.log(`constructor ${this.nodeName} `, this.innerHTML);
    }

    connectedCallback() {
      console.log(`${this.nodeName} connected ${this.innerHTML}`);
    }
  }
  customElements.define("ex-form", class extends BaseClass {});
  customElements.define("ex-input", class extends BaseClass {});
</script>
<ex-form>
  <ex-input></ex-input>
  <ex-input></ex-input>
</ex-form>
<ex-form>
  <ex-input></ex-input>
</ex-form>


谢谢丹尼的解释。你的观点真的很有帮助,给了我一个好的起点来更好地理解这个过程。现在我明白了,我的问题涉及到浏览器如何读取HTML的许多细节,你的回答帮助我更好地掌握了这一点。如果没有其他人提供更深入的解释,我将标记您的答案为已接受。 - Dario
1
我添加了“ex-form”被定义为“首先”,以更好地解释为什么。 - Danny '365CSI' Engelman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接