Event对象与自定义事件
事件对象
当为DOM元素添加一些事件的回调函数后,事件被触发时,会传给回调函数一个Event对象作为第一个参数;而这个Event对象包含关于触发的事件的一些信息及处理方法。
常用属性
bubbles:Boolean(只读), 表明事件是否冒泡;cancelable:Boolean(只读), 表明是否可以取消事件的默认行为;currentTarget:Element(只读),事件处理程序当前正在处理事件的那个元素;defaultPrevented:Boolean(只读), 为true表示已经调用了preventDefault()(DOM3级事件中新增)detail:Integer(只读),与事件相关的细节信息;eventPhase:Integer(只读),调用事件处理程序的阶段:1表示捕获阶段,2表示『处于目标』(即currentTarget与target一致时),3表示冒泡阶段;target:Element(只读),事件的目标;type:String(只读),被触发的事件的类型;view:AbstractView(只读),与事件关联的抽象视图。等同于发生事件的window对象;
整理自《JavaScript 高级程序设计》
常用方法
preventDefault():Function(只读),取消事件的默认行为。如果cancelable是true,则可以使用这个方法;stopImmediatePropagation():Function(只读),取消事件的进一步捕获或冒泡,同时阻止任何事件处理程序被调用(DOM3级事件中新增)stopPropagation():Function(只读),取消事件的进一步捕获或冒泡。如果bubbles为true,则可以使用这个方法;
整理自《JavaScript 高级程序设计》
DOM事件流
“DOM2级事件”规定的事件流包括三个阶段:事件捕获阶段、处于目标阶段和事件冒泡阶段。
构建自定义事件
构建一个自定义事件的关键就是:
-
拦截原生事件,阻断原事件传播:利用
addEventlistener的第三个参数,可以在某父级DOM上事件传播的捕获阶段触发回调函数,然后使用stopPropagation方法阻止原事件的进一步传递; -
构造自定义
Event对象:利用Event构造函数构造一个自定义属性的事件对象; -
派发自定义事件:使用
EventTarget对象自带的dispatchEvent方法进行事件对象的派发;
addEventlistener方法
1 | target.addEventListener(type, listener[, useCapture]) |
addEventListener可以为DOM绑定一个DOM2级事件的监听处理,一般第三个参数useCapture很少使用,其作用就是该事件是否在捕获阶段触发,默认为false,因此设置为true时可在捕获阶段触发监听处理函数!
创建Event对象
event = new Event(typeArg, eventInit);
通过Event构造函数可以创建一个自定义属性的Event对象,相当于回调函数接收的第一个参数;
typeArg:事件的名称;eventInit:事件的设置选项,为一个对象,该对象可以使用以下属性:bubbles:Boolean类型,表示该事件是否可以冒泡,默认值为false;cancelable:Boolean类型,表示该事件是否可以使用preventDefault()方法进行取消,默认为false;composed:Boolean类型,事件是否会在影子DOM根节点(shadow root DOM)之外触发侦听器,默认为false;
dispatchEvent()
EventTarget.dispatchEvent(event)
EventTarget:一般为触发事件时Event对象的target属性所指向的DOM节点;event:Event对象;
使用该方法就相当于某个DOM节点触发了某个event事件;
案例:自定义tap事件
由于现在的移动端设备的屏幕多是触摸屏,因此H5针对触摸屏特别制定了适用于触摸设备的TouchEvent事件规范,这使得触摸屏的点击事件变得更加灵敏了;
为啥使用click事件就不灵敏了?由于一些历史原因,现在的移动端浏览器对于click事件和touch event事件的执行顺序遵守如下规则:touchstart->touchmove->touchend->wait 300ms->click;没错,click要在所有的touch event执行完后延迟300ms再执行;
因此,如果在移动端使用click事件在点击时会出现一个很明显的延迟,对于用户体验来说是不利;其中一个解决办法就是利用TouchEvent封装一个tap点触事件,消除300ms的延迟:
1 | function initTap(eventType = 'tap') { |
上面给出的initTap方法实际上是在body元素上(也就是全局)劫持TouchEvent事件,只要判断不是touchmove事件,那么在touchend事件阶段就会在target对象上派发一个自定义的tap事件,即相当于在touchend事件后马上触发,因此也就没有click事件的300ms延迟,反应特别灵敏;这种方法可以直接在Vue中利用v-on/@进行监听(如@tap="xxx"),十分方便!
而且TouchEvent在移动端的兼容性非常好,可以大胆的使用:
