阻止事件执行的三种方法(preventDefault、stopImmediatePropagation、stopPropagation)横向对比

最新更新时间:2020年05月27日10:57:02
《猛戳-查看我的博客地图-总有你意想不到的惊喜》

本文内容:Event对象的一些知识点,事件注册、事件对象、阻止事件

概述

Event 接口表示在 DOM 中发生的任何事件; 一些是用户生成的(例如鼠标或键盘事件),而其他由 API 生成(例如指示动画已经完成运行的事件,视频已被暂停等等)。

为DOM元素注册事件处理函数的三种方式
  • 方式一:EventTarget.addEventListener
myButton.addEventListener('click', function(){alert('Hello world');}, false);
  • 方式二:HTML 属性
<button onclick="alert('Hello world!')">
  • 方式三:DOM 元素属性
myButton.onclick = function(event){alert('Hello world');};
三种方式的实例
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>

    </style>
</head>
<body>
<div id="div" onclick="htmlAttr()">123</div>
</body>
<script>
	functionhtmlAttr(){
		console.log(1);
	}
    let div = document.getElementById('div')
    div.addEventListener('click', function(){console.log(2);}, false);
    div.onclick = function(event){console.log(3);}; 
</script>
</html>

输出的结果:3 2

    let div = document.getElementById('div')
    div.addEventListener('click', function(){console.log(2);}, false);
    div.onclick = function(event){console.log(3);};
    function htmlAttr(){
        console.log(1);
    }

输出的结果:3 2

	functionhtmlAttr(){
		console.log(1);
	}
    let div = document.getElementById('div')
    div.addEventListener('click', function(){console.log(2);}, false);

输出的结果:1 2

    let div = document.getElementById('div')
    div.addEventListener('click', function(){console.log(2);}, false);
    	functionhtmlAttr(){
		console.log(1);
	}

输出的结果:1 2

  • 总结:方式三可以覆盖方式二,方式一最晚执行
DOM Event 接口中阻止事件执行的三个方法
  • event.preventDefault

取消事件(如果该事件可取消)。阻止默认行为,比如:页面滚动、复选框选中、在文本编辑域中阻止有效的文本输入

使用 Event.cancelable 来检查该事件是否支持取消。为一个不支持cancelable的事件调用preventDefault()将没有效果。

  • event.stopImmediatePropagation

场景一:同一DOM元素上相同的多个事件按照先后顺序执行的行为被终止。
如果有多个相同类型事件的事件监听函数绑定到同一个元素,当该类型的事件触发时,它们会按照被添加的顺序执行。如果其中某个监听函数执行了 event.stopImmediatePropagation() 方法,则当前元素剩下的监听函数将不会被执行。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>

    </style>
</head>
<body>
<div id="sup">
    <div id="sub">123</div>
</div>
</body>
<script>
    let sub = document.getElementById('sub')
    sub.addEventListener('click', function(e){
        e.stopImmediatePropagation()
        console.log(3);
        }, false);
    sub.addEventListener('click', function(e){
        console.log(4);
    }, false);
</script>
</html>

输出的结果:3

场景二:阻止事件冒泡,祖先元素上的相同事件不会执行

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>

    </style>
</head>
<body>
<div id="sup" onclick="htmlAttr()">
    <div id="sub">123</div>
</div>
</body>
<script>
    function htmlAttr(){
        console.log(1);
    }
    let sup = document.getElementById('sup')
    let sub = document.getElementById('sub')
    sup.addEventListener('click', function(){console.log(2);}, false);
    sub.addEventListener('click', function(e){
        e.stopImmediatePropagation()
        console.log(3);
        }, false);
</script>
</html>

输出的结果:3

对这个特定的事件而言,没有其他监听器被调用。这个事件既不会添加到相同的元素上,也不会添加到以后将要遍历的元素上(例如在捕获阶段)。

  • event.stopPropagation

只包含event.stopImmediatePropagation中的场景二。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>

    </style>
</head>
<body>
<div id="sup" onclick="htmlAttr()">
    <div id="sub">123</div>
</div>
</body>
<script>
    function htmlAttr(){
        console.log(1);
    }
    let sup = document.getElementById('sup')
    let sub = document.getElementById('sub')
    sup.addEventListener('click', function(){console.log(2);}, false);
    sub.addEventListener('click', function(e){
        e.stopPropagation()
        console.log(3);
        }, false);
    sub.addEventListener('click', function(e){
        console.log(4);
    }, false);
</script>
</html>

输出的结果:3 4

event.preventDefault应用场景
  • 当移动一个可拖动元素(比如悬浮球)时,需要阻止页面滚动
onTouchStart(e){
	let _this = this;
	document.body.addEventListener('touchmove', _this.preventScroll, {passive: false});//passive 参数不能省略,用来兼容ios和android
}

onTouchEnd(e){
	let _this = this;
	document.body.removeEventListener('touchmove', _this.preventScroll);
}

preventScroll(e){
	e.preventDefault();//阻止页面滚动
}

render(){
	return <div
			onTouchStart={(e)=>{this.onTouchStart(e)}}
			onTouchMove={(e)=>{this.onTouchMove(e)}}
			onTouchEnd={(e)=>{this.onTouchEnd(e)}}
			></div>
}
event.stopImmediatePropagation应用场景
  • react中阻止事件监听器冒泡:页面中的图片位置和数量不定,当用户点击图片时需要进行放大预览,如果图片的祖先元素绑定了click事件,此时不需要触发
let _this = this;
document.addEventListener('click',function(e){
	let dom = e.target;
	let src = e.target.getAttribute('src');
	//可以进行预览的图片域名为wansahobo
	if(dom.tagName.toLowerCase() == 'img' && src.indexOf('wanshaobo') > -1){
		e.stopImmediatePropagation();//阻止祖先元素的click事件触发
		_this.previewImg(src);//放大预览
	}
},false);
event.stopPropagation应用场景
  • 阻止祖先元素上方式一和方式二的相同类型注册事件,但不能阻止方式三
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>

    </style>
</head>
<body>
<div id="sup" onclick="htmlAttr()">
    <div id="sub">123</div>
</div>
</body>
<script>
    function htmlAttr(){
        console.log(1);
    }
    let sup = document.getElementById('sup')
    let sub = document.getElementById('sub')
    sup.addEventListener('click', function(){console.log(2);}, false);
    sub.addEventListener('click', function(e){
        e.stopPropagation()
        console.log(3);
        }, false);
    sub.addEventListener('click', function(e){
        console.log(4);
    }, false);
    sup.onclick = function(event){console.log(5);};
</script>
</html>

输出的结果:3 4 5

横向对比
  • 在事件注册方式一EventTarget.addEventListener中,横向对比三种阻止事件的方法
-preventDefaultstopImmediatePropagationstopPropagation
阻止祖先元素上的事件绑定方式一
阻止祖先元素上的事件绑定方式二
阻止祖先元素上的事件绑定方式三
阻止元素自身的事件绑定方式一
阻止元素自身的事件绑定方式二
阻止元素自身的事件绑定方式三
阻止浏览器默认行为
event对象实例
clickDiv(e){
	console.log(e.target);//被点击的元素
	console.log(e.currentTarget);//绑定该事件的元素
}

render(){
	return <div onClick={(e)=>{this.clickDiv(e)}}></div>
}
Demo源码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>

    </style>
</head>
<body>
<!-- 2 -->
<div id="sup" onclick="supC()">
    <div id="sub"  onclick="subC()">123</div>
</div>
</body>
<script>
    let sup = document.getElementById('sup')
    function supC(){
        console.log(1);
    }
    sup.onclick = function(event){console.log(2);};
    sup.addEventListener('click', function(e){
        console.log(3);}, false);
    sup.addEventListener('click', function(){
        console.log(4);
        }, false);

    let sub = document.getElementById('sub')
    function subC(){
        console.log(5);
    }
    sub.addEventListener('click', function(e){
        // e.preventDefault()
        // e.stopImmediatePropagation()
        // e.stopPropagation()
        console.log(6);
        }, false);
    sub.addEventListener('click', function(e){
        console.log(7);
    }, false);
    sub.onclick = function(event){console.log(8);};
</script>
</html>
参考资料

感谢阅读,欢迎评论^-^

打赏我吧^-^

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值