1.解释以下概念:事件传播机制、阻止传播、取消默认事件、事件代理
-
基础
什么是事件?
JavaScript和HTML的交互是通过事件实现的。事件是某个行为或者触发,比如点击、鼠标移动,图片加载等。
什么是事件流?
事件流描述的是从页面中接收事件的顺序。当用户点击了一个有嵌套关系的元素时,那是先点击的是用户本身想要点击的被嵌套的元素,还是嵌套元素的父元素?这里有三种事件传播的模型:事件冒泡,事件捕获,DOM事件流。
1.事件冒泡:事件开始时由最具体的元素接收,然后逐级向上传播到较为不具体的元素
2.事件捕获:不太具体的节点更早接收事件,而最具体的元素最后接收事件,和事件冒泡相反(ie低版本没有捕获)
3.DOM事件流:DOM2级事件规定事件流包括三个阶段,事件捕获阶段,处于目标阶段,事件冒泡阶段,首先发生的是事件捕获,为截取事件提供机会,然后是实际目标接收事件,最后是冒泡阶段
-
事件传播机制
当一个事件发生以后,它会在不同的DOM节点之间传播。这种传播分为三个阶段:
- 第一阶段,“捕获阶段”。:事件从document开始向下传,一直传到触发的目标节点上,在这个过程中会依次检测是否有节点绑定了事件的监听函数,如果有就会执行。
- 第二阶段,目标阶段:事件到达目标节点,并且触发监听函数。
- 第三阶段,冒泡阶段:从目标节点依次上传,直到document,再依次判断是否有节点绑定了监听函数。
这种三阶段的传播模型,会使得一个事件在多个节点上触发,比如会在捕获阶段和冒泡阶段在一个节点上执行两次。
-
阻止传播
如果有特殊情况,需要事件在某个节点上停止传播,就可以使用stopPropagation()
取消事件进一步捕获或冒
泡,防止再触发定义在别的节点上的监听函数,但是不包括在当前节点上新定义的事件监听函数
document.querySelector('#box') = function(e){
e.stopPropagation() //阻止传播
}
-
取消默认事件
取消浏览器对当前事件的默认行为,像有些元素时有默认的事件的,比如标签,在点击的时候默认会打开所含的超链接。如果想要自定义点击
链接的操作,就可以通过
preventDefault()
取消事件默认行为
document.querySelector('a') = function(e){
e.preventDefault() //阻止默认事件
}
-
事件代理
由于事件会在冒泡阶段向上传播到父节点,因此可以把子节点的监听函数统一处理。指定一个事件处理程序,就可以管理某一类型的所有事件
document.querySelector('ul').addEventListener('click', function(event){
if(event.target.tagName.toLowerCase() === 'li'){ //或者if(e.target.classList.contains('box'))用class来选择
//监听ul下面的所有li
}
})
如果之后再在ul
里面添加li
,监听函数也可以监听新增的li
2.写一个 Demo,演示事件传播的过程,演示阻止传播的效果
捕获阶段还是冒泡阶段,可以通过addEventListener
第三个参数cancelable
属性来控制。默认是falsse
为冒泡阶段,可以设置为true
变成捕获阶段
html+css
container
box
target
js
如果想让事件在 box冒泡阶段 停止
3.解释DOM2事件传播机制
如果用单独的事件绑定,比如
document.querySelector('.button').onclick = function(){
console.log('1')
}
document.querySelector('.button').onclick = function(){
console.log('2')
}
//2
想让.button
在被点击的时候触发两个事件,此时第二个监听函数会覆盖第一个,最后的输出 结果只有2
这个时候不要把onclick
当成一个触发时间,要把它看成一个“属性”,那么后面的“属性”会覆盖掉前面的“属性”
- box1
- box2
document.querySelectorAll('.box').onclick = function(){
console.log(this.innerText)
}
//一个都输出不了
因为选择的是一个数组,没有onclick,除非用数组的forEach
去遍历每一个数组,但是写起来又特别的麻烦
DOM2级事件定义了两个方法用于处理指定和删除事件处理程序的操作:
addEventListener
removeEventListener
所有的DOM节点都包含这两个方法,并且它们都接受三个参数:
1.事件类型
2.事件处理方法
3.布尔参数,如果是true表示在捕获阶段调用事件处理程序,如果是false,则是在事件冒泡阶段处理
这时,想要实现上面的效果就很容易了
document.querySelector('.button').addEventListener('click', function(){
console.log('1')
},false)
document.querySelector('.button').addEventListener('click', function(){
console.log('2')
},false)
//1
//2
4.补全代码
要求:
- 当点击按钮开头添加时在
- 这里是 元素前添加一个新元素,内容为用户输入的非空字符串;当点击结尾添加时在最后一个 li 元素后添加用户输入的非空字符串.
- 当点击每一个元素li时控制台展示该元素的文本内容。
- 这里是
- 饥人谷
- 任务班
5.onlick与addEventListener的区别
- onclick事件在同一时间只能指向唯一对象
- addEventListener给一个事件注册多个listener
- addEventListener对任何DOM都是有效的,而onclick仅限于HTML
- addEventListener可以控制listener的触发阶段(捕获/冒泡)。对于多个相同的事件处理器,不会重复触发,不需要手动使用removeEventListener清除
- IE9使用attachEvent和detachEvent