场景:由于需求的原因,在React中混用了原生事件,发现e.stopPropagation();
阻止事件冒泡无效。后期发现在React中有合成事件和原生事件,这两种事件阻止冒泡的方式不一样。
Q:合成事件
在jsx中直接绑定的事件,如<span className = 's0' onClick = {this.cancel}>取消</span>
就是合成事件。
Q:原生事件
domNode.addEventListener('click',self.refClick);
Q:阻止事件冒泡
- 阻止合成事件间的冒泡,用
e.stopPropagation();
var RepoList = React.createClass({
getInitialState: function() {
return {
count: 0
};
},
handleClick: function(e){
e.stopPropagation(); // 阻止合成事件间的冒泡
this.setState({count:++this.state.count});
},
testClick: function(){
console.log('test');
},
render: function() {
return (
<div ref="test" onClick={()=>this.testClick()}>
<p>{this.state.count}</p>
<a ref="update" onClick={(e)=>this.handleClick(e)}>更新</a>
</div>
);
}
});
- 阻止合成事件与最外层document上的事件间的冒泡,用
e.nativeEvent.stopImmediatePropagation();
var RepoList = React.createClass({
getInitialState: function() {
return {
count: 0
};
},
handleClick: function(e){
e.nativeEvent.stopImmediatePropagation(); // 阻止合成事件和document上的事件冒泡
this.setState({count:++this.state.count});
},
componentDidMount() {
document.addEventListener('click', () => {
console.log('document');
});
},
render: function() {
return (
<div ref="test">
<p>{this.state.count}</p>
<a ref="update" onClick={(e)=>this.handleClick(e)}>更新</a>
</div>
);
}
});
ReactDOM.render(
<RepoList/>,
document.getElementById('example')
);
- 阻止合成事件与除最外层document上的原生事件上的冒泡,通过判断
e.target
来避免
var RepoList = React.createClass({
getInitialState: function() {
return {
count: 0
};
},
handleClick: function(e){
this.setState({count:++this.state.count});
},
componentDidMount() {
let dom = this.refs.test;
dom.addEventListener('click', (e) => {
if (e.target&&e.target.matches('a')){
return;
}
console.log('test');
});
},
render: function() {
return (
<div ref="test">
<p>{this.state.count}</p>
<a ref="update" onClick={(e)=>this.handleClick(e)}>更新</a>
</div>
);
}
});
Q:添加到document
上的事件如何查看
document.addEventListener('click', () => {
console.log('document');
});
添加到document
上的事件在浏览器上查看的时候需要勾选Ancestors
。会同时显示其祖先绑定的事件。