6

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

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);
     }
 }
4

1 回答 1

3

+1 感谢您发布一个有趣的问题。

这种行为似乎符合W3C 的建议

从事件目标到树顶部的 EventTargets 链是在事件的初始分派之前确定的。如果在事件处理过程中对树进行了修改,则事件流将根据树的初始状态进行。

这可能有助于解释这里发生的事情。DOM 树似乎在气泡传播到父元素之前已被修改,此时事件将针对该位置的树中的元素(如果有)。

在这种情况下,触发事件的元素将从树中移除。它不是冒泡到下一个元素,而是冒泡到现在已经在初始元素所在的元素集合中占据其位置的元素,如果有的话。

于 2017-06-29T02:06:07.157 回答