捕获与冒泡
<div class="one">
<div class="two">
<div class="three">内容</div>
</div>
</div>
我们在点击 内容 这两个字的时候,都可以当做点击了one、two、three这三个(子元素被点击时也相当于父元素被点击),他们的调用顺序是通过你的选择来进行:
从外到内(即:one到three)找监听函数,叫:事件捕获
从内到外(即:three到one)找监听函数,叫:事件冒泡
我们可以通过事件绑定API设置:xxx.addEventListener('click',fn,bool) //bool为真就是捕获,bool为假就是冒泡,不设置的话默认为假
W3C事件模型
先捕获(父元素=>子元素)再冒泡?(子元素=>父元素)
PS:先捕获是肯定的,但是再冒泡可以被终止
在我们的事件中会有一个对象(简称:a)会被传给所有监听函数,事件结束后,a对象就会消失(setTimeout会读取不到它,需要使用的话,把这个东西赋值给另一个容器即可。如:const t = a.currentTarget
就是把 currentTarget 的引用复制到 t)
target 与 currentTarget
一、区别
a.target
用户操作的元素
a.currentTarget
程序员监听的元素
this就是a.currentTarget(不推荐使用)
二、举例
</div>
<span>文字</span>
</div>
用户点击了文字,那么a.target就是span,而a.currentTarget就是div
三、特殊情况
在只有一个div被监听(不考虑父子元素同时被监听)的情况下,函数分别在捕获阶段和冒泡阶段同时被监听了click事件,那么用户点击的元素就是开发者监听的元素。
这种情况下谁先监听谁先执行。(即:先捕获再冒泡无用,谁代码再前谁先执行)
取消冒泡
先说明:捕获不能被终止,但是冒泡可以!
a.stopPropagation()
可中断冒泡 (多用于封装某些独立的组件)
不可取消冒泡
有些特殊情况不可取消冒泡,搜索scroll event ,查看Bubbles和Cancelable
(Bubbles是该事件是否可以冒泡;Cancelable是开发者是否可以取消冒泡。看到no就是不可取消)
自定义事件
浏览器自带了很多事件(详见MDN:https://developer.mozilla.org/zh-CN/docs/Web/Events)
开发者可以在自带事件外自定义事件,并且还可以设置能否冒泡,只要添加:bubbles:true
、cancelable:false
......即可设置(这个就是可以冒泡且不可取消冒泡)
事件委托
本质:让一个元素帮我监听一个我本该监听的东西
情况一、给 100 个按钮添加点击事件
监听这 100 个按钮的 父元素(上层元素),待冒泡的时候判断 target 是这 100 个的按钮中的哪一个,再作出相应事件。
情况二、给目前DOM页面内还不存在元素(动态元素)添加事件
监听父元素,等点击时,再来判断当前的操作的元素是否为我们想要监听的元素即可
所以事件委托就是通过监听祖先元素来 实现 节约内存、监听动态元素的方法
阻止浏览器默认事件
例如:
var $a = document.getElementsByTagName("a")[0];
$a.onclick = function(e){
alert("跳转动作被我阻止了")
e.preventDefault();
//return false;//也可以
}
所以通过使用 xx.preventDefault() 的这个方法,可以阻止取消默认的事件