阻止事件執行的三種方法(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中,橫向對比三種阻止事件的方法
- preventDefault stopImmediatePropagation stopPropagation
阻止祖先元素上的事件綁定方式一
阻止祖先元素上的事件綁定方式二
阻止祖先元素上的事件綁定方式三
阻止元素自身的事件綁定方式一
阻止元素自身的事件綁定方式二
阻止元素自身的事件綁定方式三
阻止瀏覽器默認行爲

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>

參考資料

感謝閱讀,歡迎評論^-^

打賞我吧^-^

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章