一、捕获与冒泡
-
JavaScript与HTML之间的交互是通过事件来实现的,事件就是文档或者浏览器窗口发生特定的交互瞬间。
-
事件流是指从页面中接收事件的顺序。
- 捕获阶段:浏览器先检查元素的最外层祖先,查找是否有对应的监听函数(onclick事件处理程序),如果是则运行它,如果不是则继续向里找,执行相同的操做,直至到达实际点击的元素。
- 冒泡阶段:浏览器首先检查被点击的元素,看是否有监听函数(onclick事件处理程序)。如果没有就向上移动到parentNode继续寻找,直至找到监听函数并运行。
-
DOM事件模型:先捕获再冒泡
1.1事件绑定API:addEventListener
attachEvent('onclick',fn) //IE,冒泡
addEventListener('click',fn)//网景,捕获
addEventListener('click',fn,bool)// W3C
- 如果bool不传或者为falsy,就让fn走冒泡,如果浏览器在冒泡阶段发现有fn监听函数,就调用fn,提供事件信息
- 如果bool为true,就让fn走捕获,如果浏览器在捕获阶段发现有fn监听函数,就调用fn,提供事件信息
- JS只是调用DOM提供的addEventListner这个API,DOM事件不属于JS的功能
1.2target和currentTarget
-
e.target是用户操作的元素
-
e.currentTarget是程序员监听的元素
eg:div>span{文字},用户点击了文字,e.target就是span,e.currentTarget就是div
1.3DOM事件模型特例
只有一个div被监听(不考虑父子同时被监听),fn分别在捕获阶段和冒泡阶段监听click事件,用户点击的元素就是开发者监听的
div.addEventListner('click',f1)
div.addEventListner('click',f2,true)
// f1和f2谁先执行?取决于代码顺序,谁先监听谁先执行
1.4取消冒泡和阻止滚动
捕获不可以取消,但是冒泡可以
e.stopPropagation() //可以中断冒泡,浏览器不再往上走
-
所有
冒泡皆可取消,默认动作有的可以取消有的不能取消 -
Cancelable 是用来取消(也可以说阻止)默认动作的
-
Bubbles是说明该事件是否冒泡
但是有的事件不可以取消默认动作,比如scroll event
那么如何阻止滚动?取消特定元素的wheel和touchstart的默认动作
addEventListner('wheel',(e)=>{
e.preventDefault()
}) // 阻止鼠标滚轮滚动
addEventListner('touchstart',(e)=>{
e.preventDefault
}) // 阻止移动端触屏滚动
::-webkit-scrollbar{width:0!important} /*隐藏网页滚动条*/
二、事件委托
事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。
-
场景一:给100个按钮添加点击事件,怎么处理?
监听100个按钮的祖先,等冒泡的时候判断target是不是100个按钮中的一个
-
场景二:监听目前不存在的元素的点击事件,怎么处理?
监听祖先,等点击的时候看看是不是要监听的元素
-
事件委托的优点:节省监听数(内存);可以监听动态元素
3.1封装事件委托
写出这样一个函数on('click','#testDiv','li',fn),当用户点击#testDiv里面的li元素时,调用fn函数
function on (eventType,element, selector, fn) {
if(!(element instanceof Element){
element = document.querySelector(element)
}
element.addEventListener(eventType, (e) => {
let el = e.target // 用户操作的元素
while (!el.matches(selector)) {// 用户操作的元素不匹配选择器
if (element === el) { // 用户操作的元素无法找到,退出当前循环
el = null
break
}
el = el.parentNode //判断上一级元素是否匹配选择器
}
el && fn.call(el, e, el)
})
return element
},