浅谈JS事件

什么是JS事件

在<<JS高级程序设计>>中,是这么定义事件的: 事件,就是文档或浏览器窗口中发生的一些特定的交互瞬间。以现在的眼光来看,其实不仅仅是在浏览器窗口了,JS在小程序、PWA等环境下,也在发挥其特定的作用。

事件处理程序

鼠标点击(click)、双击(dblclick),页面加载完成(load)都是事件。我们可以通过以下几种形式来为事件指定处理程序

  • HTML事件处理程序
        <input type="button" value="click me" onclick="alert(event.type)">
    
  • DOM0级事件处理程序
        let btn = document.querySelector('#btn')
        btn.onclick = function(){}
    
  • DOM2级事件处理程序
    也是我们最常是用的方式。通过addEventListener()和removeEventListener()来添加和移除。addEventListener接受三个参数:事件名称,回调函数和一个布尔值(true:捕获,默认false冒泡)。在IE浏览器上,则是使用attachEvent()和detachEvent()来添加和移除事件,另外在IE8极其更早版本,只支持事件冒泡。我们可以通过封装一个通用事件函数,做浏览器判断处理。
    let EventUtil = {
        addHandle(element,type,handle){
            if(element.addEventListener){
                element.addEventLister(type,handle,false)//现在基本上都是使用冒泡了
            }else if(element.attachEvent){
                element.attachEvent(`on${type}`,handle)
            }else{
                element[`on${type}`] = handle
            }
        },
        removeHandle(){
            if(element.addEventListener){
                element.removeEventListener(type,handle,false)
            }else if(element.attachEvent){
                element.detachEvent(`on${type}`,handle)
            }else{
                element[`on${type}`] = null
            }
        }
    }
    

事件流

我们设定一个大的DIV1,里面放DIV2,再在DIV2里面放入DIV3。在设计JS事件机制的时候,这个时候点击DIV3,有两种思路:

  • 一种顺序是1=>2=>3, 先在1上触发,再依次往下,
  • 另外一种思路是3=>2=>1,在最里面的先触发,依次往上。

前者就叫事件的捕获(event capturing),后者叫事件的冒泡(event bubbling)。
我们在每一个div上加上捕获,和冒泡的事件监听

    document.querySelector('#box1').addEventListener('click', function() {
        console.log('box1 捕获')
    }, true)
    document.querySelector('#box1').addEventListener('click', function() {
        console.log('box1 冒泡')
    }, false)
    document.querySelector('#box2').addEventListener('click', function() {
        console.log('box2 捕获')
    }, true)
    document.querySelector('#box2').addEventListener('click', function() {
        console.log('box2 冒泡')
    }, false)
    document.querySelector('#box3').addEventListener('click', function() {
        console.log('box3 捕获')
    }, true)
    document.querySelector('#box3').addEventListener('click', function() {
        console.log('box3 冒泡')
    }, false)
    // 点击BOX3 最终执行结果是
    box1 捕获 => box2 捕获 => box3 捕获 => box3 冒泡 => box2 冒泡 => box1 冒泡

在浏览器中,事件流分为三个阶段 捕获=>处于目标阶段=>冒泡。值得注意的是,处于目标阶段,HTML事件处理程序会先于捕获事件执行。

    <div id="box3" onclick="console.log('box3 html event')"></div>
    这个事件会在 box3捕获前执行

事件委托

如果事件处理程序过多,我们就要用到事件委托的机制了。事件委托主要是利用了事件冒泡的机制,通过在父元素上添加事件来处理相关逻辑。比如下面的列表,如果我们在每个li上添加事件,点击获取其id,如果li特别多,会导致内存占用高,引起性能问题,事件委托则不会。

 		<ul id="list">
          <li id="li1">1</li>
          <li id="li2">2</li>
          <li id="li3">3</li>
      </ul>
      document.querySelector('#list').addEventListener('click',function(e){
          console.log('e===>',e.target.id)
      })

事件对象

属性/方法类型说明
bubblesBoolean事件是否冒泡
cancelableBoolean是否可以取消事件的默认行为
currentTargetElement事件处理程序当前正在处理的元素
defaultPreventedBoolean为true表示调用了preventDefault()
detailInteger与事件相关的细节信息
eventPhaseInteger事件阶段1:捕获,2:处于目标,3:冒泡
preventDefault()Function取消事件默认行为,需要cancel
stopImmediatePropagation()Function取消事件的进一步捕获或冒泡,同时组织任何事件处理程序被调用
stopPropagation()Function取消事件的进一步捕获或冒泡
targetElement事件目标
trustedBoolean为true代表浏览器生成,为false表示由开发人员通过js
typeString触发事件的类型
viewAbstractView与事件关联的抽象视图,等同于发生时间的window对象

在前面例子中,我们用到了e.target.id来获取li的id,这个参数e实际上是事件对象event,其包含了有关于这个时间的信息,比如类型,元素等。
这些属性中,要区分清楚地是currentTarget与target可能相同,也可能不同。当点击的事件正好是在事件目标上触发的时候,这两个值是相同的,否则不同。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值