事件流
可以想象画在一张纸上的一组同心圆,如果把手指放在圆心上,那么手指指向的不是一个圆,而是纸上所有的圆。
事件流描述的是从页面中接受事件的顺序。
触发顺序,先捕获,后冒泡
事件冒泡
即事件开始时由最具体的元素接受,然后逐级向上传播到较为不具体的节点。
结构上(非视觉上)嵌套关系的元素,会存在事件冒泡的功能,即同一事件,自子元素冒泡向父元素。(自底向上)。
focus,blur,change,submit,reset,select 等事件不冒泡。
比如下面这个例子,点击.box
,会先后打印出 box
,content
,wrapper
。
1 | <div class="wrapper"> |
1 | let wrapper = document.getElementsByClassName('wrapper')[0]; |
事件捕获
结构上(非视觉上)嵌套关系的元素,会存在事件捕获的功能,即同一事件,自父元素捕获至子元素。(自顶向下)。
下面的代码与事件冒泡的代码的不同就是 false
改成了 true
,会先后打印出 wrapper
,content
,box
。
1 | wrapper.addEventListener('click', function () { |
结合
先捕获,后冒泡,这里注意一下 boxBubble
和 box
的打印顺序,因为 boxBubble
是先绑定的,所以先执行。
1 | // 冒泡 |
取消冒泡
此时控制台只会打印出 boxBubble
。
1 | wrapper.addEventListener('click', function () { |
阻止默认事件
- return false; 以对象属性的方式注册的事件才生效
- event.preventDefault(); W3C标注,IE9以下不兼容
- event.returnValue = false; 兼容IE
1 | // 第一种方法 return false 对 addEventListener 不生效 |
阻止 a
标签的默认事件,点击会回到顶部。
1 | <!-- void相当于return --> |
事件对象
event || window.event
事件源对象:
- event.target 火狐只有这个
- event.srcElement IE只有这个
- chrome上面的都有
1 | // 获取事件源对象 |
事件委托
事件冒泡 + 事件源对象结合,避免过多地遍历 li。
优点:
- 性能:不需要循环所有的元素一个个绑定事件
- 灵活:当有新的子元素时不需要重新绑定事件
1 | <ul> |
1 | let ul = document.getElementsByTagName('ul')[0]; |