js 事件流

258 阅读3分钟

参考文章
对事件流的深入理解
高级教程13章节

基本概念

有事件作用于节点时,有两种类型

  • 冒泡流【IE提出】: 由具体元素向外(上) 传递事件
  • 捕获【网景提出】: 由最外层元素向具体元素向内(下) 传递事件 w3c 同时兼容两种事件流,早期IE浏览器只有冒泡;

理论上,在绑定的一个事件里,只会发生其中一个事件流;但浏览器在执行过程中,不按照该理论执行;

DOM0 事件

直接赋值给节点的事件

var dom = document.getElementId('xx')
dom.onclick = function(e){
    // todo
}

DOM2级事件

它会经历3个阶段:

假设所有元素都绑定事件情况, 执行的顺序是 捕获 - 目标 - 冒泡;

  • 捕获: 从上往下,从 window 向下捕获: event.target,到达目标元素;
  • 到达目标元素: 事件已达到目标元素; (在目标上同时存在捕获和冒泡事件时, 先定义什么,就执行什么. 其非目标节点不会这样)
  • 冒泡: 从下往上,从当前元素向父节点不断传递;
var dom = document.getElementId('xx')
dom.addEventListern('click', function(e) {
    // todo
}, useCapture=true)

dom0 和 dom2 区别

事件的绑定js实现【捕获/冒泡】

  • onclick (dom0): 所有浏览器保持统一,只有冒泡,旧事件会被替代;

  • addEventListener (dom2): 可以自由设置 捕获 或 冒泡;缺点是早期 IE 只有冒泡;

DOM2 事件 addEventLitern 详解

addEventListener方法具有第三个可选参数 useCapture
其默认值为false,事件将在 冒泡阶段中发生;
如果为true,则事件将在 捕获阶段 中发生。

根据 addEventListener 的第三个参数只能是二选一;

委托事件执行过程中, e.target 和 e.currentTarget 区别?

e.target : 目标元素;
e.currentTarget: 冒泡/捕获 阶段的执行元素;

委托事件是根据什么事件流实现的?

  1. 在最上层的元素上绑定事件的处理函数;
  2. 自顶层节点向目标元素执行
  3. 委托事件内写判断 e.target === e.currentTarget 处理目标元素;
  4. 委托事件结束;

优点: 解决性能问题,减少绑定多个事件的大小占用的优点;

目标元素执行顺序是不是按照 事件定义 顺序?????

不会严格按照 捕获 - 到达目标 - 冒泡 的顺序来处理;
真实情况:目标元素的执行顺序,是按照绑定的顺序处理的;【参考文章里有案例,先绑定在什么阶段就会先执行】
真实业务里,如果一个元素绑定了两次事件,执行的顺序至关重要,需要知道这个知识点;

如何阻止冒泡?

  • addEventListener: 使用 e.stopPropagation 都能阻止 捕获/冒泡;

特点: stopPropagation 在同一个元素绑定多个事件时,stopPropagation 执行后会阻止掉该元素其他绑定事件;【具体阻止哪些,和事件阶段绑定顺序有关系

如何阻止默认行为?

  • return e.preventDefault 标准技术
  • return e.returnValue 早期IE的
  • return false 阻止对象属性的事件【onclick 绑定事件】
function cancelHandler(event){
    var event=event||window.event;//兼容IE
    
    //取消事件相关的默认行为
    if(event.preventDefault)    //标准技术
        event.preventDefault();
    if(event.returnValue)    //兼容IE9之前的IE
        event.returnValue=false;
    return false;    //用于处理使用对象属性注册的处理程序
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>事件冒泡</title>
</head>
<body>
    <div>
        <p id="parEle">我是父元素    <span id="sonEle">我是子元素</span></p>
    </div>
</body>
</html>
<script type="text/javascript">
var sonEle = document.getElementById('sonEle');
var parEle = document.getElementById('parEle');

parEle.addEventListener('click', function () {
    alert('父级 冒泡');
}, false);
parEle.addEventListener('click', function () {
    alert('父级 捕获');
}, true);

sonEle.addEventListener('click', function () {
    alert('子级冒泡');
}, false);
sonEle.addEventListener('click', function () {
    alert('子级捕获');
}, true);

</script>

DOM3 事件

一些特殊事件: focus、blur、scroll 等等(待后续更新)