javascript - 导入 "wrong"顺序的Web组件时出错

标签 javascript ecmascript-6 web-component circular-dependency

我构建了一个包含多个 HTML Web 组件的小型库,供公司内部使用。有些组件是相互依赖的,所以我也相互导入。直到最近,我对这种方法还没有遇到严重的问题,但现在在加载使用此类相互依赖的组件的 HTML 页面时遇到错误消息。

我在一个小例子中隔离了这个问题。请查看以下三个文件。

<强> test-container.js

import { TestItem } from "./test-item";

export class TestContainer extends HTMLElement {
  constructor() {
    super();

    this.attachShadow({ mode: "open" }).innerHTML = `
      <style>
        * {
          position: relative;
          box-sizing: border-box;
        }
        :host {
          contain: content;
          display: block;
        }
      </style>
      <div>
        <slot></slot>
      </div>
    `;
  }

  connectedCallback() {
    if (!this.isConnected) {
      return;
    }

    for (const node of this.childNodes) {
      if (node instanceof TestItem) {
        //...
      }
    }
  }
}

customElements.define("test-container", TestContainer);

<强> test-item.js

import { TestContainer } from "./test-container";

export class TestItem extends HTMLElement {
  constructor() {
    super();

    this.attachShadow({ mode: "open" }).innerHTML = `
      <style>
        * {
          position: relative;
          box-sizing: border-box;
        }
        :host {
          contain: content;
          display: block;
        }
      </style>
      <div>
        <slot></slot>
      </div>
    `;
  }
}

customElements.define("test-item", TestItem);

<强> index.html

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <title>Test</title>
  <script type="module" src="/test-container"></script>
  <script type="module" src="/test-item"></script>
  <style>
    test-container {
      width: 600px;
      height: 400px;
      background: lightblue;
      border: 1px solid;
    }
    test-item {
      width: 200px;
      height: 200px;
      background: lightgreen;
      border: 1px solid;
    }
  </style>
</head>
<body>
  <test-container>
    <test-item></test-item>
  </test-container>
</body>
</html>

这段代码似乎工作正常。

但是,如果我切换两个 <script> index.html 中的标签文件时,开发者工具控制台显示以下错误:

Uncaught ReferenceError: Cannot access 'TestItem' before initialization
    at HTMLElement.connectedCallback (test-container:30)
    at test-container:37

由于我在许多组件中导入了多个模块,因此我想按字母顺序对它们进行排序(为了清楚起见)。在我的测试示例中它很好,但在我的实际代码中它不是......

所以基本上我希望我的模块完全独立于其他模块导入它们的顺序。有什么办法可以实现这一点吗?

非常欢迎所有建议。但是,我不允许安装和使用任何外部/第三方软件包。甚至连使用 jQuery 也是不允许的。因此,解决方案应该仅包含普通的 JS、普通的 CSS 和普通的 HTML5,并且它至少应该在最新的 Google Chrome 和 Mozilla Firefox Web 浏览器中正常工作。

最佳答案

当你无法控制Elements的加载顺序时,
您必须处理元素中的依赖

使用: https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry/whenDefined

whenDefined 返回一个 Promise!

所以你的<test-container>代码需要类似:

  customElements.whenDefined('test-item')
   .then( () => {
       //execute when already exist or became available
   });

https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry/whenDefined

有一个更详细的示例等待页面中所有未定义的元素


依赖项

事件驱动的方法可能可以更好地摆脱依赖性。

制造<test-item>connectedCallback 中调度事件 X

<test-container>监听事件 X 并对项目执行某些操作

然后您可以添加 <another-item> 无需进行更改 <test-container>

也许是默认的slotchange事件可以提供帮助:
https://developer.mozilla.org/en-US/docs/Web/API/HTMLSlotElement/slotchange_event

.

成功遇见了welke aanpak je ook kiest

关于javascript - 导入 "wrong"顺序的Web组件时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56703992/

相关文章:

javascript - 在 Node 4.x 中导出 ES6 类意外的保留字

html - 如何获取 &lt;script type ="module"> 中的 document.currentScript.ownerDocument?

javascript - 使用导入的 Javascript 函数 ES6 访问主文件中的全局变量

css - 在 polymer 中加载外部 css 的条件模板

data-binding - 使用 polymer 1.0 在两个 polymer 元素之间进行数据绑定(bind)

javascript - 我可以在 Android 浏览器中仅使用 javascript 启动 Intent 吗?

javascript - 使用 RegEx 替换 Div 字符串

c# - 将 javascript 日期时间转换为 C#/VB.NET 日期时间

javascript - 当行数很大时,AJAX 调用不显示任何数据

javascript - Polymer - 遍历模板中的对象