JavaScript 浏览器中的Event

Yukino 475 2021-12-29

一、Event对象

  1. type:发生事件的类型,JS支持的事件类型非常多,大致可以分为以下几类:

    • 设备无关输入事件:这类事件和特定输入设备相关;例如mousemove、keydown、touchmove等;

    • 设备相关输入事件:这类事件并不与特定输入设备相关,它可以由多种设备触发;例如:click既可以由鼠标触发也可以由触屏触发;

    • 用户界面事件:通常定义在应用界面的表单元素上触发,这类事件包括:focus、change和submit

    • 状态变化事件:有些事件并不直接由用户活动触发,而是由网络或者浏览器触发;例如:window的onload、online、popstate等事件

    • API特定事件:有一些HTML及相关规范定义的WebAPI包含自己的事件类型;例如:video和audio元素定义了一系列事件(waiting、playing、seeking等)

  2. target:发生事件的对象

  3. currentTarget:对于传播的事件,这个属性是注册当前事件处理程序的对象

  4. timeStamp:表示事件发生时间的时间戳(毫秒),不是绝对时间

  5. isTrusted:表示这个事件是否是由浏览器自身触发,如是,则这个属性为true,如果是JS触发,这个属性为false

二、事件处理函数注册

事件处理函数注册可以通过两种方式:

  • 第一种是直接设置事件处理程序,按照惯例所有的事件处理程序属性都是由on加事件名组成,并全部为小写,例如:onclick、onchange

  • 第二种是使用addEventListener注册目标对象(EventTarget)的事件处理程序

    target. addEventListener(type, listener, options)

    • type(String):事件类型

    • listener(Function):事件处理函数

    • options(Object,可选):可选参数对象

      • capture: Boolean,默认为false,表示 listener 会在该类型的事件捕获阶段传播到该 EventTarget 时触发。

      • once: Boolean,默认为false,表示 listener 在添加之后最多只调用一次。如果是 true, listener 会在其被调用之后自动移除。

      • passive:Boolean,默认为false,设置为true时,表示 listener 永远不会调用 preventDefault()

    addEventListener还有一种简写方式,可以使用capture直接作为options传入,即addEventListener(target, listener, true)

    注意:使用onclick只能注册一个事件处理函数,而使用addEventListener可以注册多个事件处理函数,并且onclick注册的事件处理函数与addEventListener注册的事件处理函数互不影响,没有直接的关联,并按照注册的顺序执行

    三、移除事件处理函数

    移除事件处理函数与注册相对应,有两种对应方式:

    • 对于直接设置的处理函数,可以用null覆盖处理函数,例如可以直接设置target.onclick = null,来移除原本traget上的click的处理函数;

    • 对于addEventListener注册的处理函数,使用使用removeEventListener来移除,同样的,removeEventListener也接收三个参数,typelisteneroptions,不同的是options只有capture一个选项,值得注意的是,若注册时capture设置为true,那么在remove是也需要设置为true。

    四、事件处理上下文

    事件触发时调用事件处理程序的方式:

    target.handler()

    其中,target为事件目标,handler为事件处理程序,熟悉this自然就能判断这里的上下文了,这里就不再做过多解释。

    五、事件传播

    如果事件的目标是window或者其它独立对象,浏览器对这个事件的响应就是简单的调用该对象上对应的事件处理函数(也就是前面说的第一种添加事件的方式添加的处理函数,后续用onevent代替,例如:onclick),如果事件目标是Document或者其它文档元素,那么事件会经历以下三个阶段(可以参考这个**例子**结合理解):

    1. 捕获阶段,在onevent触发之前,事件会从上(根元素,window对象)至下(子元素)传递,此过程中,通过addEventListener注册的并且capture设置为true的处理函数将会被调用;

    2. 调用onevent

    3. 冒泡阶段,多数事件都会“冒泡”,冒泡阶段事件会从子元素向上传播,一直到document对象,最后到window对象(除了focus、blur和scroll事件,document的load事件会冒泡,但到Document就会停止冒泡,不会到达window对象),在冒泡的过程中父元素的onevent和通过addEventListener注册的并且capture设置为false的处理函数会先后被调用。

    六、事件取消

    浏览器会对很多用户事件作出响应,无论你是否有在代码中指定,比如,用户在一个链接上单击鼠标,浏览器就会打开这个链接。

    对于某些场景,如果想阻止这些默认动作,可以在使用addEventListener添加事件处理函数时,将options中的passive设置为true,也可以重新注册一个事件处理函数,在其中调用preventDefault()函数。

    亦或者,你想取消事件的传播,可以使用stopPropagation,取消事件出波,但是,这个对象上其它的处理函数依然会被调用,如果不想触发这些函数,可以使用stopImmediatePropagation。

    七、派发自定义事件

    在某些情况下我们可能需要手动触发某个事件或者自定义一个事件,这时我们就可以自己创建一个Event或者CustomEvent,然后调用dispatchEvent方法派发这个事件,可以看下面的**例子**:

    <input />
    <script>
    const event = new Event('input');
    const element = document.querySelector('input');
    element.addEventListener('input', () => {
      console.log('input');
    })
    element.value = '123'; // 此语句不会触发input事件
    element.dispatchEvent(event);

     const customEvent = new CustomEvent('ohhh', {
       detail: { msg: '野炊2要出了!' }
    })
     element.addEventListener('ohhh', (e) => {
       console.log('ohhh');
       console.log(e.detail.msg);
    });
     element.dispatchEvent(customEvent);
    </script>

在创建CustomEvent时,可以设置detail属性,传递事件相关的信息,具体的使用方法可以参见CustomEvent()-MDN


# 前端 # JS