gpt4 book ai didi

javascript - 添加新的 Web 组件时的线程问题

转载 作者:行者123 更新时间:2023-11-30 00:31:52 27 4
gpt4 key购买 nike

我目前正在尝试构建一个 web 组件,它将另一个组件作为其模板的一部分。但是当尝试访问该子组件的 JS API 时,我得到一个 functionName is undefined 错误。

将我的模板附加到 DOM 时,我可以使用 querySelector 访问新添加的节点,但不能访问其组件 API(即 publicAPI),显然该元素尚未完全初始化。即使我将 DOMNodeInserted 绑定(bind)到该元素,API 仍未定义。

但是只要我将它包装到延迟为 0 毫秒的 setTimeout 中,这是一种在不同线程中运行代码的方法,它就会起作用。

在使用 HTML 导入加载组件脚本时,启用 webcomponent 功能的 Chrome 和 Firefox 中不会发生这种情况。

我想找到这个线程问题的原因,并尽可能避免任何 setTimeout。

这是我的代码,或者是jsFiddle

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/0.5.5-rc1/webcomponents-lite.min.js"></script>
</head>
<body>

<div is="x-div"><b>test</b></div>

<template id="x-div-tmpl">
<section is="x-component" class="wrapper"></section>
</template>

<script>
var XDiv = document.registerElement('x-div', {
extends: 'div',
prototype: Object.create(HTMLDivElement.prototype, {
createdCallback: {
value: function() {
var _this = this,
template = document.querySelector('#x-div-tmpl'),
wrapper = template.content.querySelector('.wrapper');

// move all child nodes inside the template wrapper container
while (this.firstChild) {
wrapper.appendChild(this.firstChild);
}
var tmpl = document.importNode(template.content, true);
this.wrapper = tmpl.querySelector('.wrapper');
this.wrapper.addEventListener('DOMNodeInserted', function(e){
if(e.target === _this.wrapper) {
console.log('DOMNodeInserted', _this.wrapper, ' ' + typeof _this.wrapper.publicAPI); // HTMLElement, undefined
}
});
this.appendChild(tmpl);

console.log(this.wrapper, typeof this.wrapper.publicAPI); // HTMLElement, undefined
setTimeout(function(){
console.log('setTimeout', _this.wrapper, typeof _this.wrapper.publicAPI); // HTMLElement, function
}, 0);
}
}
})
});


var XComponent = document.registerElement('x-component', {
extends: 'section',
prototype: Object.create(HTMLDivElement.prototype, {
createdCallback: {
value: function() {
console.log('XComponent:createdCallback');
}
},
attachedCallback: {
value: function() {
console.log('XComponent::attachedCallback');
}
},
publicAPI: {
value: function() {
console.log('XComponent::publicAPI');
}
}
})
});
</script>
</body>
</html>

最佳答案

内部组件的 cratedCallbackattachedCallback 应该发出一个事件:

attachedCallback: {
value: function () {
var event = document.createEvent("HTMLEvents");
event.initEvent("attached", true, true);
event.eventName = "attached";
this.dispatchEvent(event);
}

然后你的外部组件会监听它:

this.wrapper.addEventListener('attached',
function (e) {
console.log(_this.wrapper, ' ' + typeof _this.wrapper.publicAPI);
});

您的完整工作代码:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/0.5.5-rc1/webcomponents-lite.min.js"></script>
</head>
<body>

<div is="x-div"><b>test</b></div>

<template id="x-div-tmpl">
<section is="x-component" class="wrapper"></section>
</template>

<script>
var XDiv = document.registerElement('x-div', {
extends: 'div',
prototype: Object.create(HTMLDivElement.prototype, {
createdCallback: {
value: function ()
{
var _this = this,
template = document.querySelector('#x-div-tmpl'),
wrapper = template.content.querySelector('.wrapper');

// move all child nodes inside the template wrapper container
while (this.firstChild)
{
wrapper.appendChild(this.firstChild);
}
var tmpl = document.importNode(template.content, true);
this.wrapper = tmpl.querySelector('.wrapper');

this.wrapper.addEventListener('attached', function (e)
{
if (e.target === _this.wrapper)
{
console.log(_this.wrapper, ' ' + typeof _this.wrapper.publicAPI); // HTMLElement, function
}
});

this.appendChild(tmpl);
}
}
})
});

var XComponent = document.registerElement('x-component', {
extends: 'section',
prototype: Object.create(HTMLDivElement.prototype, {
createdCallback: {
value: function ()
{
console.log('XComponent:createdCallback');
}
},
attachedCallback: {
value: function ()
{
console.log('XComponent::attachedCallback');

var event = document.createEvent("HTMLEvents");
event.initEvent("attached", true, true);
event.eventName = "attached";
this.dispatchEvent(event);
}
},
publicAPI: {
value: function ()
{
console.log('XComponent::publicAPI');
}
}
})
});
</script>
</body>
</html>

关于javascript - 添加新的 Web 组件时的线程问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29149630/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com