我正在创建一个与 Vite 捆绑在一起的简单网站,但没有像 React、Vue、Svelte 等外部框架。该网站具有使用不同数据的重复 HTML 元素。我想为此使用自定义元素。我使用自定义元素而不是完整的 Web 组件,因为我希望能够使用全局样式表。数据位于外部 JSON 文件中。我遇到了计时问题,这些问题导致难以及时将数据获取到自定义元素以便对其进行配置。
我的 HTML 看起来像:
<!doctype html>
<html lang="en">
<head>...</head>
<body>
<main>
<my-element data-content-id="0"></my-element>
<another-element data-content-id="1"></another-element>
<my-element data-content-id="2"></my-element>
<another-element data-content-id="3"></another-element>
</main>
<script type="module" src="/main.js"></script>
</body>
</html>
main.js:
import MyElement from "./custom-elements/MyElement.js"
import AnotherElement from "./custom-elements/AnotherElement.js"
const init = () => {
// load external config
const configFile = "/config.json"
fetch(configFile)
.then(config => config.json())
.then(config => {
console.log("[Main] app initiated in main.js")
const myElement = new MyElement(config)
const anotherElement = new AnotherElement(config)
}
})
.catch(error => console.error('Error:', error))
}
init()
MyElement.js:
class MyElement extends HTMLElement {
constructor(config) {
super()
this.config = config
console.log("constructor")
if (this.config) {
console.log("calling useData from constructor", this.config)
this.useData(this.config)
}
}
useData(prop) {
console.log("useData")
// ... logic here ...
}
connectedCallback() {
console.log("connected callback")
if (this.config) {
console.log("calling useData from callback", this.config)
this.useData(this.config)
}
this.innerHTML = `
<div>
...
</div>
`;
}
}
window.customElements.define('my-element', MyElement)
export default MyElement;
当我查看日志时,我发现
constructor
和 connected callback
记录在 [Main] app initiated in main.js
之前。然后,当实例化 MyElement 类时,再次调用/记录 constructor
,这次带有数据,因此 useData
运行/记录。但此时,我已经运行了构造函数两次,并且无法访问 DOM 中的自定义元素来使用数据。
所以,总而言之,即使我在数据加载之前没有实例化
main.js
中的类,构造函数也会被调用两次:一次是当自定义元素出现在 DOM 中时(我猜,无论如何,它是在获取数据之前),以及使用数据实例化时(在获取数据之后)一次。加载数据并实例化类后,我将无法访问通过 connectedCallback
获得的自定义元素。
有没有办法在自定义元素中使用外部获取的数据并正确计时?
<main>
<my-element data-content-id="0"></my-element>
<another-element data-content-id="1"></another-element>
<my-element data-content-id="2"></my-element>
<another-element data-content-id="3"></another-element>
</main>
<script type="module" src="/main.js"></script>
您在 DOM 中的 Web 组件被解析之后加载脚本。
因此 constructor
和
connectedCallback
(在opening 标签上触发)已经运行。 您现在有了一个全局
init()
,它告诉?您的组件要做什么? 也许反转逻辑,让Web组件
加载数据(可以记忆)
您可以通过添加最小可重现示例 StackOverflow Snippet 来帮助我们回答您的问题。它将帮助读者一键执行您的代码。并一键帮助创建答案。