Javascript 事件模型

1.事件的监听

JS有三种方法可以为事件绑定监听函数

  • HTML的 on-属性:只会在冒泡阶段触发;
<!-- 正确 -->
<body onload="doSomething()"> 

<!-- 错误 -->
<body onload="doSomething">
  • 元素节点的事件属性:只会在冒泡阶段触发;
window.onload = doSomething;
div.onclick = function (event) {
    console.log('触发事件');
};

以上两种方法就是所谓的 DOM 0级事件。

  • EventTarget.addEventLister();(只兼容IE8以上,attachEvent(event.type, handle )可以兼容IE8以下,只支持冒泡阶段触发)
window.addEventListener('load', doSomething, false);
target.addEventListener(type, listener[, useCapture]);
  • type:事件名称;
  • listener:监听函数,事件发生时,会调用该监听函数;
  • useCapture:布尔值,表示监听函数是否在捕获阶段(capture)触发,默认是false,表示在冒泡阶段被触发;
  • 第三个参数除了useCapture,还可以是一个属性配置对象;该属性有以下几个属性:
    • capture:表示该事件是否在捕获阶段被触发;
    • once:表示监听函数是否只触发一次,然后就自动移除;
    • passive:表示监听函数不会调用事件的preventDefault方法,如果监听函数调用了,浏览器会忽略这个要求,然后监控台输出一行警告。

上面的方法就是所谓的 DOM 2级事件。

2.事件的传播

一个事件发生后,会在子元素和父元素之间传播。这种传播分成三个阶段:

  • 第一阶段:捕获阶段,从 window 对象传导到目标节点(上层到底层);
  • 第二阶段:目标阶段,在目标节点上触发。(在目标元素同时注册的冒泡和捕获事件,先注册先执行);
  • 第三阶段:冒泡阶段,从目标节点传导会 window 对象。

3.阻止默认事件

  • return false;阻止通过 on 方式绑定事件的默认事件;
ele.onclick = function() {
    …… // 你的代码
    return false; // 通过返回 false 值阻止默认事件行为
};
  • event.preventDafult();阻止通过 addEventListener 添加事件的默认事件;
element.addEventListener("click", function(e){
    var event = e || window.event;
    …… 
    event.preventDefault( ); // 阻止默认事件
}, false);
  • event.returnValue = false;阻止通过 attachEvent() 添加事件的默认时间(主要是兼容IE8以下);
element.attachEvent("onclick", function(e){
    var event = e || window.event;
    ……
    event.returnValue = false; // 阻止默认事件
}, false);
  • 阻止事件的兼容写法
// 阻止浏览器的默认行为
function stopDefault( e ) {
    // 阻止默认浏览器动作(W3C)
    if ( e && e.preventDefault ) {
        e.preventDefault(); // IE中阻止函数器默认动作的方式
    } else {
        window.event.returnValue = false;
    }
    return false;
}

4.阻止事件冒泡

w3c 的方法是 e.stopPropagation()(阻止事件的传播),IE 则是使用 e.cancleBubble = true;

阻止事件冒泡的兼容写法

function stopBubble (e) {
    // 如果提供了事件对象,则这是一个非IE浏览器 
    if ( e && e.stopPropagation ) {
        // 因此它支持W3C的stopPropagation()方法
        e.stopPropagation();
    } else {
        // 否则,我们需要使用IE的方式来取消事件冒泡
        window.event.cancelBubble = true;
    }
}

5.事件代理

由于事件会在冒泡阶段向上传播到父节点,因此可以把子节点的监听函数绑定到父节点上,有父节点的监听函数处理多个子元素的事件。这种方法就是事件的代理。

6.事件对象

  • event.target:指的是触发事件的元素;
  • event.currentTarget:指的是绑定事件的元素(this);
  • event.preventDefault():阻止默认事件,取消事件对当前元素的影响,不会阻止事件的传播;
  • event.stopPropagation():阻止事件传播,防止再触发定义在别的节点上的监听函数,但不包括当期节点上的其他的事件监听函数;
  • event.stopImmediatePropagation():阻止同一事件的其他监听函数调用,不管监听函数是定义在其他节点还是当前节点

7.React 和 Vue 在事件处理上的差异

  • Vue 的事件对象是原生对象,事件被挂载到当前元素上;
    • 通过 event.target 获取到的是触发当前事件的元素,比如一个按钮;
    • 通过 event.currentTarget 获取到的是绑定当前事件的元素,比如我是在当前按钮上绑定的事件,那获取到的就是当前的这个按钮
  • React 的事件对象不是原生的对象,是 React 封装的合成对象,所有的事件都被挂载在 document 上;
    • event 不是原生的事件对象,它的原型是 SyntheticEvent;
    • 我们可以通过 event.target 来获取触发当前事件的元素,比如一个按钮;
    • 通过 event.currentTarget 来获取绑定当前事件的元素,那么你获取到的也是这个按钮,但是这是个假象;
    • 我们可以通过 event.nativeEvent 来获取到原生的事件;
    • 通过 event.nativeEvent.target 来获取触发当前事件的元素,比如一个按钮;
    • 通过 event.nativeEvent.currentTarget 来获取绑定当前事件的元素,这个时候你会发现你获取到的是 Document 对象;
  • 那 React 为什么要使用这样一个合成对象呢?
    • 更好的兼容性和跨平台;
    • 挂载到 document 上,减少内存消耗,避免频繁解绑;
    • 方便事件的统一管理;

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值