在React中,我们可以在创建element
的时候,传入事件和处理函数,这些事件会被做为合成事件
来处理,当然,有些时候,我们也需要定义原生事件,比如给document
绑定事件。有些情况下,就需要通过阻止事件冒泡来实现预期的交互效果。下面是几个简单的demo
Demo
比如有如下的代码:
import React from 'react'
class Demo1 extends React.Component{
onClickInner(e){
console.log('inner div')
}
onClickOuter(e){
console.log('outer div')
}
render(){
return <div onClick={this.onClickOuter}>
<div onClick={this.onClickInner}>inner div</div>
</div>
}
}
当我们点击 inner div时,控制台输出结果:
inner div
outer div
这两个事件都是合成事件,在点击时,两个事件会依次冒泡到document
,由统一的事件监听器处理。如果希望阻止onClickOuter
触发,可以在onClickInner
内调用e.stopPropagation()
。需要注意的是,这里的e
是合成事件实例,调用stopPropagation
也只能阻止合成事件的冒泡。
假如我们将onClickOuter
通过原生事件来绑定:
class App extends React.Component {
onClickInner(e) {
e.stopPropagation();
console.log("inner div");
}
onClickOuter(e) {
console.log("outer div");
}
componentDidMount() {
this.outer.onclick = this.onClickOuter;// 通过DOM 0级绑定
}
render() {
return (
<div ref={ref => (this.outer = ref)}>
<div id='inner' onClick={this.onClickInner}>123</div>
</div>
);
}
}
虽然在onClickInner
内调用了 e.stopPropagation
, 但是原生事件还是会通过冒泡来触发,而且会先于onClickInner
, 控制台输出:
outer div
inner div
这是因为onClickInner
合成事件被触发的时候,说明点击事件已经通过冒泡传递到了document
,在这个过程中,便会经过外层的div,进而触发该原生事件。这也说明了,合成事件的stopPropagation
只能阻止合成事件的冒泡。即使我们在这里通过e.nativeEvent
获取到原生事件并调用stopPropagation
,也无济于事,因为上面已经说了,在该合成事件被触发的时候,已经冒泡到了document.
那么我们该通过什么方式来阻止原生事件onClickOuter
被触发呢:
既然在onClickInner
处理不了,只能在onClickOuter
内处理了:
onClickOuter(e) {// 这里e是原生事件
if(e.target && e.target.id === 'inner'){
return ;
}
console.log("outer div");
}
如果我们将原生事件绑定在了document
上:
class App extends React.Component {
constructor(props) {
super(props);
// this.bindDocument();
}
onClickInner(e) {
console.log("inner div");
}
componentDidMount() {
this.bindDocument();
}
bindDocument() {
document.addEventListener("click", function(e) {
console.log("document");
});
}
render() {
return (
<div id="inner" onClick={this.onClickInner}>
123
</div>
);
}
}
上面代码中,在组件挂载完毕后,再给document绑定click事件,这时候,React合成事件已经注册完成,当点击时,document上的click事件会依据绑定顺序的先后依次执行,所以控制台会输出:
inner div
document
如果希望阻止后绑定的事件触发,可以在onClickInner
内调用stopImmediatePropagation
:
如果有多个相同类型事件的事件监听函数绑定到同一个元素,当该类型的事件触发时,它们会按照被添加的顺序执行。如果其中某个监听函数执行了 event.stopImmediatePropagation() 方法,则当前元素剩下的监听函数将不会被执行。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。