原生js、jQuery、vue.js、react 阻止事件冒泡
一、什么是事件冒泡
一条鱼往上吐泡泡,这个泡泡就是事件,一直往上冒的过程中去把它经过的所有元素,只要这个元素身上有相同事件,就会去执行该元素的该事件,没有相同事件就不会去执行
二、冒泡特点
1、冒泡看的是代码层级,从里往外冒泡
2、拥有相同类型事件的元素才会被执行
3.不同事件就是不同泡泡
三、阻止事件冒泡
并不是所有事件都需要事件冒泡,我们需要让事件执行完自身的该事件后,不再往上冒,这就是阻止事件冒泡
obj为当前执行该事件的元素对象
1. 原生js写法
方法一
if(evt.stopPropagation) {
evt.stopPropation();
}else{
evt.cancelBubble=true;
方法二
function stopPro(evt){
var e = evt || window.event;
//returnValue如果设置了该属性,它的值比事件句柄的返回值优先级高。把这个属性设置为 fasle,
//可以取消发生事件的源元素的默认动作。
//window.event?e.returnValue = false:e.preventDefault();//默认事件
window.event?e.cancelBubble=true:e.stopPropagation();
}
2. jQuery 写法
$(function() {
// 用click事件
$(document).click( function(event) {
console.log('click');
event.stopPropagation();
});
// 用delegate事件
$(document).delegate('.delete','click', function(event) {
console.log('delegate');
event.stopPropagation();
});
// 用live事件
$('.delete').live('click', function(event) {
console.log('live');
event.stopPropagation();
//return false;
});
// 新添加的a标签
$('#add').click(function() {
var html = '<a href="javascript:;" class="delete">new html 1</a>';
$('#box').append(html);
});
$('#box').click(function() {
console.log('box emit');
});
});
3. vue.js阻止事件冒泡
方法一:
<div id="app">
<div @click="on2()">
<!--<input type="button" value="冒泡" @click.stop="on()"/>第一种给click后面添加stop-->
</div>
new Vue({
el:"#app",
methods:{
on:function(){
alert(1)
},
on2:function(){
alert(2)
}
}
})
方法二
<div id="app">
<div @click="on2()">
<input type="button" value="冒泡" @click="on($event)" />
</div>
</div>
<input type="button" value="冒泡" @click="on($event)" />
<script>
new Vue({
el: "#app",
on: function(ev) {
alert(1)
ev.cancelBubble = true
},
on2: function() {
alert(2)
}
}
})
react 阻止事件冒泡
// 1 在没有涉及到原生事件注册只有react事件时,用e.stopPropagation()阻止冒泡
import React, { Component } from 'react';
import './App.css';
class App extends Component {
handleClickTestBox = (e) => {
console.warn('handleClickTestBox: ', e);
}
handleClickTestBox2 = (e) => {
console.warn('handleClickTestBox2: ', e);
}
handleClickTestBox3 = (e) => {
e.stopPropagation();
console.warn('handleClickTestBox3: ', e);
}
render() {
return (
<div
className="test-box"
onClick={this.handleClickTestBox}
>
<div
onClick={this.handleClickTestBox2}
>
<div
onClick={this.handleClickTestBox3}
>
</div>
</div>
</div>
);
}
}
export default App;
//2、当用document.addEventListener注册了原生的事件后,用e.stopPropagation()是不能阻止与document之间的冒泡,这时候需要用到e.nativeEvent.stopImmediatePropagation()方法
import React, { Component } from 'react';
import './App.css';
class App extends Component {
componentDidMount() {
document.addEventListener('click', this.handleDocumentClick, false);
}
handleDocumentClick = (e) => {
console.log('handleDocumentClick: ', e);
}
handleClickTestBox = (e) => {
console.warn('handleClickTestBox: ', e);
}
handleClickTestBox2 = (e) => {
console.warn('handleClickTestBox2: ', e);
}
handleClickTestBox3 = (e) => {
// 阻止合成事件的冒泡
e.stopPropagation();
// 阻止与原生事件的冒泡
e.nativeEvent.stopImmediatePropagation();
console.warn('handleClickTestBox3: ', e);
}
render() {
return (
<div
className="test-box"
onClick={this.handleClickTestBox}
>
<div
onClick={this.handleClickTestBox2}
>
<div
onClick={this.handleClickTestBox3}
>
</div>
</div>
</div>
);
}
}
export default App;
//3、阻止合成事件与非合成事件(除了document)之间的冒泡,以上两种方式都不适用,需要用到e.target 判断
import React, { Component } from 'react';
import './App.css';
class App extends Component {
componentDidMount() {
document.addEventListener('click', this.handleDocumentClick, false);
document.body.addEventListener('click', this.handleBodyClick, false);
}
handleDocumentClick = (e) => {
console.log('handleDocumentClick: ', e);
}
handleBodyClick = (e) => {
if (e.target && e.target === document.querySelector('#inner')) {
return;
}
console.log('handleBodyClick: ', e);
}
handleClickTestBox = (e) => {
console.warn('handleClickTestBox: ', e);
}
handleClickTestBox2 = (e) => {
console.warn('handleClickTestBox2: ', e);
}
handleClickTestBox3 = (e) => {
// 阻止合成事件的冒泡
e.stopPropagation();
// 阻止与原生事件的冒泡
e.nativeEvent.stopImmediatePropagation();
console.warn('handleClickTestBox3: ', e);
}
render() {
return (
<div
className="test-box"
onClick={this.handleClickTestBox}
>
<div
onClick={this.handleClickTestBox2}
>
<div
id="inner"
onClick={this.handleClickTestBox3}
>
</div>
</div>
</div>
);
}
}
export default App;