阻止事件执行的三种方法(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');};

三种方式的实例


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Titletitle>
    <style>

    style>
head>
<body>
<div id="div" onclick="htmlAttr()">123div>
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() 方法,则当前元素剩下的监听函数将不会被执行。


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Titletitle>
    <style>

    style>
head>
<body>
<div id="sup">
    <div id="sub">123div>
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

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


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Titletitle>
    <style>

    style>
head>
<body>
<div id="sup" onclick="htmlAttr()">
    <div id="sub">123div>
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中的场景二。


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Titletitle>
    <style>

    style>
head>
<body>
<div id="sup" onclick="htmlAttr()">
    <div id="sub">123div>
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应用场景

  • 阻止祖先元素上方式一和方式二的相同类型注册事件,但不能阻止方式三

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Titletitle>
    <style>

    style>
head>
<body>
<div id="sup" onclick="htmlAttr()">
    <div id="sub">123div>
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中,横向对比三种阻止事件的方法
- preventDefault stopImmediatePropagation stopPropagation
阻止祖先元素上的事件绑定方式一
阻止祖先元素上的事件绑定方式二
阻止祖先元素上的事件绑定方式三
阻止元素自身的事件绑定方式一
阻止元素自身的事件绑定方式二
阻止元素自身的事件绑定方式三
阻止浏览器默认行为

event对象实例

clickDiv(e){
     
	console.log(e.target);//被点击的元素
	console.log(e.currentTarget);//绑定该事件的元素
}

render(){
     
	return <div onClick={
     (e)=>{
     this.clickDiv(e)}}></div>
}

Demo源码


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Titletitle>
    <style>

    style>
head>
<body>

<div id="sup" onclick="supC()">
    <div id="sub"  onclick="subC()">123div>
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>

参考资料

  • Event | MDN
  • event.stopImmediatePropagation
  • 文档对象模型 (DOM)例子

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

打赏我吧^-^

你可能感兴趣的:(web前端开发)