React 点击事件冒泡 "sideways",而不仅仅是 "up"

React click event bubbling "sideways", not just "up"

我在组件中嵌套了点击事件处理程序:

class ListItem extends React.Component {
    ...
    render() {
        return (
            <div onClick={this.save}>
              ...Content...
              <span onClick={this.onDeleteClick}> (Delete)</span>
            </div>
        );
    }
    ...
}

(此 post 底部的完整、最小示例。)

此组件用作包含组件中的 "list item"。当我单击 (Delete) 时,它会按预期触发 onDeleteClick,这会回调父级,导致组件从父级组件中删除。如预期的那样,点击事件随后开始冒泡。但是,它冒泡 "up" 到父列表 中的 下一个组件。毕竟,原始目标已被删除处理程序删除。

如果我在 onDeleteClick 处理程序的顶部添加一个 e.stopPropagation() 它一切正常,但我只是想了解 为什么 click 事件被传送到一个完全不同的组件,只是为了确保那里没有任何其他确凿证据。

我目前的理论是,挂起事件队列以某种方式索引到虚拟 DOM 中,如果您在事件处理程序期间改变虚拟 DOM,冒泡事件可能会被传递到虚拟 DOM 中的错误组件。我原以为冒泡事件只是 而不是 触发,而不是在完全不同的组件上触发。

这是怎么回事?还有其他见解吗?这是一个有缺陷的设计吗?如果是,有没有关于替代方案的建议?


这是一个显示问题的最小示例:https://codepen.io/mgalgs/pen/dRJJyB

这里是固定版本:https://codepen.io/mgalgs/pen/KqZBKp

"fix" 的完整差异是:

--- orig.jsx
+++ new.jsx
@@ -32,6 +32,7 @@
     }

     onDeleteClick(e) {
+        e.stopPropagation();
         this.props.onDeleteClick(e);
     }
 }

+1 感谢您提出有趣的问题。

该行为似乎与 W3C's recommendations 一致:

The chain of EventTargets from the event target to the top of the tree is determined before the initial dispatch of the event. If modifications occur to the tree during event processing, event flow will proceed based on the initial state of the tree.

这可能在某种程度上解释了这里发生的事情。 DOM 树似乎在气泡传播到父元素之前已被修改,届时事件将以树中该位置的元素为目标(如果有)。

在此上下文中,触发事件的元素已从树中删除。事件不会冒泡到 next 元素,而是冒泡到现在已经在初始元素所在的元素集合中占据其位置的元素,如果有的话。