Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/397.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在阴影DOM中的setTimeout中更改了event.target?_Javascript_Web Component_Shadow Dom - Fatal编程技术网

Javascript 在阴影DOM中的setTimeout中更改了event.target?

Javascript 在阴影DOM中的setTimeout中更改了event.target?,javascript,web-component,shadow-dom,Javascript,Web Component,Shadow Dom,JS-Bin 外阴影DOM customElements.define('test-test',类扩展了HtmleElement{ 构造函数(){ 超级(); const node=document.createElement('template'); node.innerHTML='内部阴影DOM'; 这是阿塔奇沙多({ 模式:“打开” }).appendChild(node.content); this.shadowRoot.querySelector('#in').addEventLis


JS-Bin
外阴影DOM
customElements.define('test-test',类扩展了HtmleElement{
构造函数(){
超级();
const node=document.createElement('template');
node.innerHTML='内部阴影DOM';
这是阿塔奇沙多({
模式:“打开”
}).appendChild(node.content);
this.shadowRoot.querySelector('#in').addEventListener('click',e=>{
console.log(如target);
设置超时(()=>{
console.log(如target);
});
});
}
});
document.querySelector(“#out”).addEventListener('click',e=>{
console.log(如target);
设置超时(()=>{
console.log(如target);
});
});
我在ShadowDOM内外的事件侦听器中发现了这些不一致的行为。单击
内部阴影DOM
按钮时,控制台输出:

<button id="in">Inside Shadow DOM</button>
<test-test>...</test-test>
<button id="out">Outside Shadow DOM</button>
<button id="out">Outside Shadow DOM</button>
在Chrome、FireFox和Safari中测试。他们都有这些不一致的行为。我不知道这是预期行为还是错误

更新:
这个问题不应该结束。另一个没有回答这个问题。

这是预期的行为,不是一个bug

解释它需要太多的字符

见:


用我简单的话来说:

Javascript是单线程的。
(e)
事件
是传递给所有事件处理程序的全局对象

当您使用SetTimeout时,
事件
内容可以/将不同

我重写了您的测试代码:


功能日志(标签、颜色、范围、evt){
让composedTarget=(evt.composed&&evt.composedPath());
console.log(`c${label}\t%c${evt.target.id}`、`background:${color}`、`background:${evt.target.id};color:white`、'\n\ttarget:'、evt.target,“\n\t此:”、scope.nodeName | | |“窗口”、“\n\tcurrentTarget、evt.currentTarget、evt.currentTarget、'\n\tclickedTarget:'、evt.clickedTarget:'、evt.clickedTarget、“、evt:”、“\n\n\t:”、evt:”、evt:”、evt:“、evt:”、evt[0]);
}
定义('shadow-element',类扩展HtmleElement{
构造函数(){
super().attachShadow({mode:'open'})
.innerHTML=`单击${this.title}`;
let button=this.shadowRoot.querySelector('button');
button.onclick=e=>{
设savedTarget=e.target;
e、 点击target=e.target;
button.onclick=false;//防止双重捕获
日志(`clicked元素:${this.id}`、'lightgreen',this,e);
设置超时(()=>{
日志('timeout element','red;color:yellow',this,e)
}, 500);
};
//this.onclick=button.onclick;
}
});
提出的要点是,对阴影DOM中的元素触发的事件进行重定目标,以隐藏阴影DOM,使其不受光DOM的影响。这意味着事件对象在其生存期内将更改其目标

  • 首先在捕获阶段,当事件对象还没有到达阴影DOM时,灯光容器(此处
    )将成为该事件对象的目标
  • 然后在阴影DOM中,它将被更改为实际的阴影目标(
  • 最后,在脱离阴影DOM的冒泡阶段,它将被设置回灯光容器
因此,当您从超时记录它时,所有事件阶段都将发生,事件对象将处于此最终状态,灯光容器为
.target

customElements.define('test-test',类扩展了HtmleElement{
构造函数(){
超级();
const node=document.createElement('template');
node.innerHTML='内部阴影DOM';
这是阿塔奇沙多({
模式:“打开”
}).appendChild(node.content);
this.shadowRoot.addEventListener('click',e=>{
log(“[捕获阶段]在阴影DOM中”,例如target);
},{capture:true});
this.shadowRoot.addEventListener('click',e=>{
log(“[bubblingphase]在shadowdom中”,例如target);
},{capture:false});
}
});
document.addEventListener('click',e=>{
log(“[捕获阶段]在Light DOM中”,例如target);
},{capture:true});
document.addEventListener('click',e=>{
log(“[bubbling phase]在Light DOM中”,e.target);
},{capture:false});

那么这是否意味着如果我想在阴影dom的setTimeout中使用相同的目标,我必须在本地存储变量?@QianChen是的,当事件同步触发时,您需要从中获取它(您也可以通过
e.composedPath()[0]从打开的阴影dom外部获取它)
,但这会在超时后返回一个空数组。)这取决于您要在何处使用它。将它作为变量添加到侦听器范围内,并且它仅在该范围内可用。将它作为事件的额外属性添加,并可供处理该事件的所有处理程序使用。