解釋以下概念:事件傳播機制、阻止傳播、取消默認事件、事件代理
事件傳播機制
事件傳播機制分為三個階段
- 事件捕獲階段:事件被從document一直向下傳播到目標(biāo)元素,在這過程中依次檢查經(jīng)過的節(jié)點是否注冊了該事件的監(jiān)聽函數(shù),若有則執(zhí)行。(ie低版本沒有捕獲)
- 事件處理階段:事件到達目標(biāo)元素,執(zhí)行目標(biāo)元素的事件處理函數(shù).
- 冒泡傳播:從捕獲到事件源的元素開始往父級元素進行事件冒泡,DOM0級事件中,事件綁定函數(shù)的觸發(fā)都發(fā)生在冒泡階段
阻止傳播
stopPropagation()取消事件進一步捕獲或冒泡
阻止默認事件
preventDefault()取消事件默認行為
- 什么是事件默認行為?
-
a鏈接默認跳轉(zhuǎn) - type =
submit默認提交表單 其他瀏覽器默認行為...
-
我們不希望瀏覽器默認做什么事情,我們就給它綁定事件,怎么綁定呢?preventDefault()
<a >baidu</a>
<script>
document.querySelector('a').onclick= function(e){
//阻止默認事件
e.preventDefault()
//點擊時打印鏈接
console.log(this.href)
if(/baidu.com/.test(this.href)){
location.href = this.href
}
}
</script>
<form action="/login">
<input type="text" name="username">
<input type="submit">
</form>
<script>
document.querySelector('form').addEventListener('submit', function(evt){
//阻止默認事件
evt.preventDefault()
if(document.querySelector('input[name=username]').value === 'jirengu'){
this.submit()
}
})
</script>
事件代理
要理解事件代理,首先要明白什么是事件冒泡:當(dāng)一個元素上的事件被觸發(fā)的時候,比如說鼠標(biāo)點擊了一個按鈕,同樣的事件將會在那個元素的所有祖先元素中被觸發(fā)。這一過程被稱為事件冒泡。
<ul id="oul">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
(function(){
var oUl=document.getElementById("oul");
oUl.addEventListener('click',show,false);
function show(e) {
var targetElement=e.target||e.srcElement;
if(targetElement.nodeName.toLowerCase()==="li"){
alert(targetElement.innerHTML);
}
}
})();
</script>
看上面的這個例子,我把click事件綁定在了父元素ul上,而不是li上,于是,當(dāng)我點擊任何一個li標(biāo)簽(不管是動態(tài)生成的還是之前就有的)是,這個事件就像泡泡一樣,冒啊冒。由于我這里給ul綁定了onlick,那么這時,ul會捕獲冒泡上來的onclick事件。
我們來看一下事件代理的步驟:
- 父元素綁定事件
- 父元素知道事件的實際發(fā)生目標(biāo)是誰
- 我們要對目標(biāo)進行判斷,如果是我們需要的元素,則發(fā)生回調(diào)函數(shù)
事件代理的優(yōu)點:
- 性能不小心得到了優(yōu)化
- 動態(tài)添加的元素也能綁定事件了
寫一個 Demo,演示事件傳播的過程,演示阻止傳播的效果

阻止事件傳播
//html
<body>
<style>
.container,
.box,
.target{
border: 1px solid;
padding: 10px;
}
</style>
<button id="btn">click</button>
<div class="container">
container
<div class="box">
box
<div class="target">target</div>
</div>
</div>
</body>
//js
function $(selector){
return document.querySelector(selector)
}
var btn = $('#btn')
btn.onclick = function (e){
console.log(e)
}
btn.addEventListener('click', function(evt){
console.log(this)
console.log(btn)
console.log(evt.target)
})
$('.container').addEventListener('click', function(e){
console.log('contianer click.. in 捕獲階段')
}, true)
$('.box').addEventListener('click', function(e){
//e.stopPropagation() //阻止傳播
console.log('box click.. in 捕獲階段')
}, true)
$('.target').addEventListener('click', function(e){
console.log('target click.. in 捕獲階段')
}, true)
$('.container').addEventListener('click', function(e){
console.log('contianer click.. in 冒泡階段')
}, false)
$('.box').addEventListener('click', function(e){
//e.stopPropagation() //阻止傳播
console.log('box click.. in 冒泡階段')
}, false)
$('.target').addEventListener('click', function(e){
console.log('target click.. in 冒泡階段')
}, false)