描述事件冒泡的流程
事件冒泡基于树形dom结构,事件可以一级一级的向上冒泡,若有多个事件,先响应内层,再响应外层。若一个事件在最外层绑定的,在最内层上依旧能监听到。
事件冒泡和事件捕获
事件冒泡:事件可以一级一级的向上冒泡,若有多个事件,先响应内层,再响应外层。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| event.stopPropagation()
event.preventDefault()
event.target
event.target.dataset
event.currentTarget
event.target.matches(selector) -->
|
事件捕获:从外向内触发事件,很少用于开发。
xxx.addEventListener(‘xxx’,function(){},true) 第三个参数为true时,则触发事件捕获。
事件代理
像瀑布流,无限加载图片,由于元素太多不好每一个元素都绑定事件,所以就将事件绑定在这些图片的父元素上,通过事件冒泡去相应事件
好处是代码简洁,减少浏览器占用,但不要滥用。
面试题
编写一个通用的事件监听函数
为了解决事件代理(如瀑布流需要每个图片都有一个点击事件)将瀑布流事件绑定在父元素上,当点击父元素时,可以激发子元素的事件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| function bindEvent(element,eventType,selector,fn) { if(fn == null) {
fn = selector selector = null } element.addEventListener(eventType,e => { let target = e.target if (selector) { if (target.matches(selector)) { fn.call(target,e) } } else { fn.call(target,e) } }) }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| function bindEvent(element,eventType,fn,selector) { element.addEventListener(eventType,(event)=>{ let target = event.target if(selector) { if(target.matches(selector)) { fn.call(target,event) } } else { fn.call(target,event) } }) } let btn = document.querySelector('btn') bindEvent(btn,'click','child_div',function(e){ e.preventDefault() alert(this.innerHTML) })
|