网站搜索

typescript - 根据是否使用“defer”,网页组件的行为有所不同


我用 TypeScript 实现了一个 WebComponent,看起来像这样,并通过 WebPack 打包:

class MyTestComponent extends HTMLElement {
    // ...
    connectedCallback() {
        this.config = JSON.parse(this.innerText);
// ...
customElements.define("my-test", MyTestComponent);

在网页中它是这样使用的:

<my-test>
{
  "parts": [
    [3, "red"]
  ]
}
</my-test>

在我使用 WebPack 生成的测试页面时,这个工作正常,但如果我将组件包含到另一个页面中则会失败。我花了一些时间才弄明白,在包含脚本标签上使用 defer 属性才是关键。如果我使用 defer,组件就能正常工作。如果不使用,调用 connectCallback 时 this.innerText 是空的。

我想了解为什么 defer 会有区别,以及具体发生了什么。有人能解释一下吗?

答案#1

这与 TypeScript 或 WebPack 无关。这是标准的 Web 组件行为。

connectedCallback 会在 打开 标签时触发,其内部内容尚未解析。

使用 defer 可以在解析完 DOM 中的所有内容后声明自定义元素 AFTER

因此,当你的自定义元素 在使用之前就已被定义 时,为了让它正常工作,

你必须延迟执行,直到组件的 DOM (innerText 或 innerHTML) 被解析。

最简单的方法是等待事件循环为空时再执行:

connectedCallback() {
  setTimeout(()=>{
    this.config = JSON.parse(this.innerText);
  });
}

长回答(当 Firefox 在 2021 年 3 月之前延迟触发 connectedCallback 时)

  • 在 connectedCallback 中等待元素升级:Firefox 和 Chromium 的差异

像 FAST、Lit、LWC 和 Hybrids 这样的基类 工具,可以保护你免受这种标准行为的影响……
……让你学习的是一个工具,而不是技术。