我在组件中嵌套了click事件处理程序:
class ListItem extends React.Component {
...
render() {
return (
<div onClick={this.save}>
...Content...
<span onClick={this.onDeleteClick}> (Delete)</span>
</div>
);
}
...
}
(这篇文章底部的完整,最小的例子。)
此组件用作包含组件中的“列表项”。当我点击(Delete)
时,它会按预期触发onDeleteClick
,这会向父节点进行回调,从而导致组件从父组件中删除。然后点击事件按预期开始冒泡。但是,它会“向上”到父列表中的下一个组件。毕竟,删除处理程序已经删除了原始目标。
如果我在e.stopPropagation()
处理程序的顶部添加onDeleteClick
,一切正常,但我只是想了解为什么正在发送点击事件一个完全不同的组件,只是为了确保那里没有任何其他吸烟枪。
我当前的理论是,挂起的事件队列以某种方式被索引到虚拟DOM中,如果您在事件处理程序期间改变虚拟DOM,则冒泡事件可能会被传递到虚拟DOM中的错误组件。我原本以为冒泡事件只是不开火,而不是在一个完全不同的组件上开火。
这是怎么回事?任何其他见解?这是一个有缺陷的设计,如果是这样,有关替代品的任何建议吗?
以下是显示问题的最小示例:https://codepen.io/mgalgs/pen/dRJJyB
这是固定版本:https://codepen.io/mgalgs/pen/KqZBKp
“修复”的完整差异是:
--- orig.jsx
+++ new.jsx
@@ -32,6 +32,7 @@
}
onDeleteClick(e) {
+ e.stopPropagation();
this.props.onDeleteClick(e);
}
}
答案 0 :(得分:3)
+1感谢发布有趣的问题。
行为似乎与W3C's recommendations内联:
从事件目标到树顶部的EventTargets链 在最初发送事件之前确定。如果 在事件处理,事件流程期间对树进行修改 将根据树的初始状态继续进行。
这可能会在某种程度上解释这里发生的事情。在气泡传播到父元素之前,DOM树似乎已被修改,此时事件将以该位置中的树中的元素为目标(如果有的话)。
在此上下文中,触发事件的元素将从树中删除。而不是冒泡到 next 元素的事件,它会冒泡到现在已经在初始元素所在的元素集合中占据其位置的元素(如果有的话)。