我有一个更高阶的组件来跟踪任何组合组件的mouseover
事件。它大致是这样的:
(Component) => class TrackMouseOver extends React.Component {
handleMouseOver = (e) => {
console.log('Mouse over!');
};
render() {
return <Component {...this.props} onMouseOver={this.handleMouseOver}/>;
}
};
但是,由于React组件本身不绑定到DOM事件,因此效果不佳。除非组件处理onMouseOver
道具,否则上述HOC将无效。
在不破坏React组件的黑盒特性的情况下,总是将props转移到子元素是否更好?如果是,这样做会对性能产生重大影响吗?
答案 0 :(得分:2)
如果您开始传递处理程序函数向下,您将反对自然的事件流,因为它们通过DOM冒泡向上。
相反,使用侦听器将组件包装在处理元素中,并使用事件冒泡。
(Component) => class TrackMouseOver extends React.Component {
handleMouseOver(e) {
e.target // is the element that triggered the event
e.currentTarget // is the element this handler is attached to
}
render() {
return (
<div onMouseOver={this.handleMouseOver}>
<Component {...this.props} />
</div>
);
}
};
当您点击新div
内的其中一个元素时,该事件的生命周期为两部分。
浏览器确定事件发生在哪个顶级元素,然后该元素的哪个子元素依此类推,直到事件最终结束于没有子元素的元素 - 目标。
此序列不会触发任何事件侦听器(除非它们设置了useCapture
标志),它只是标识事件的路径。
现在已经到达事件的目标元素,事件会将捕获的路径返回到DOM的根目录,并在事件发生时触发事件侦听器。
这是附加到body
元素的事件处理程序始终触发*的原因,无论事件发生在哪个元素上。 body
是所有元素的共同祖先。
在您的情况下,您可以利用div
中任何元素的事件最终会冒泡到此事件处理程序的事实。
您可以使用event.target
确定事件来自哪个元素。
*如果某个后代元素上的事件处理程序调用{{1}}或event.preventDefault
,则不会触发事件处理程序。