解释以下概念:事件传播机制、阻止传播、取消默认事件、事件代理
事件传播机制
事件传播机制分为三个阶段
- 事件捕获阶段:事件被从document一直向下传播到目标元素,在这过程中依次检查经过的节点是否注册了该事件的监听函数,若有则执行。(ie低版本没有捕获)
- 事件处理阶段:事件到达目标元素,执行目标元素的事件处理函数.
- 冒泡传播:从捕获到事件源的元素开始往父级元素进行事件冒泡,DOM0级事件中,事件绑定函数的触发都发生在冒泡阶段
阻止传播
stopPropagation()
取消事件进一步捕获或冒泡
阻止默认事件
preventDefault()
取消事件默认行为
- 什么是事件默认行为?
-
a链接
默认跳转 - type =
submit
默认提交表单 其他浏览器默认行为...
-
我们不希望浏览器默认做什么事情,我们就给它绑定事件,怎么绑定呢?preventDefault()
<a href="http://baid.com">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>
事件代理
要理解事件代理,首先要明白什么是事件冒泡:当一个元素上的事件被触发的时候,比如说鼠标点击了一个按钮,同样的事件将会在那个元素的所有祖先元素中被触发。这一过程被称为事件冒泡。
<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
上,于是,当我点击任何一个li标签
(不管是动态生成的还是之前就有的)是,这个事件就像泡泡一样,冒啊冒。由于我这里给ul绑定了onlick
,那么这时,ul会捕获冒泡上来的onclick事件
。
我们来看一下事件代理的步骤:
- 父元素绑定事件
- 父元素知道事件的实际发生目标是谁
- 我们要对目标进行判断,如果是我们需要的元素,则发生回调函数
事件代理的优点:
- 性能不小心得到了优化
- 动态添加的元素也能绑定事件了
写一个 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)