我构建了一个包含多个 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/