1.概念

事件是元素天生自带的默认操作行为,不论我们是否给其绑定了方法,当我们操作的时候,就会把对应的事件触发。事件绑定是给元素的某个行为绑定一个方法,目的是当事件行为触发的时候,可以做一些事情。

2.DOM0事件绑定 vs DOM2事件绑定

2.1 DOM0事件绑定

  • elment.on事件行为 = function(){}
  • DOM0事件绑定的原理:给元素的私有属性赋值,当事件触发,浏览器会帮我们把赋值的函数执行,但是这样也导致了“只能给当前元素某一个事件行为绑定一个方法”,后赋值的会覆盖前边的。
  • 移除事件绑定的方式:直接赋值为null即可。

2.2DOM2事件绑定

  • element.addEventListener(event,function(){},true/false)
  • DOM2事件绑定原理:基于原型链查找,找到EventTarget.prototype上的方法并且执行,此方法执行,会把当前元素某个事件行为绑定的所有方法,存放到浏览器默认的事件池中。
  • 移除事件绑定方式。DOM2事件绑定一般采用实名函数,这样可以基于实名函数区移除事件绑定。

element.removeEventListener(event,fn,false)

  • 基于addEventListener向事件池增加方法,存在去重机制,同一个元素,同一个事件,同一个方法只能给绑定一次。
  • DOM0和DOM2可以混在一起用,执行的顺序以绑定的顺序为主。

3. 事件对象Event

3.1

给元素的事件绑定方法,当事件触发,方法执行,会默认传递一个事件对象event给函数,如果是鼠标操作,获取的是MouseEvent类的实例,鼠标事件对象。

3.2 MouseEvent常用对象属性。

clientX/clientY:获取到的是触发点相对浏览器可视区域左上角距离,不随页面滚动而改变。
pageX/Y:触发点相对文档区域左上角距离,会随着页面滚动而改变
offsetX/Y:触发点相对被触发DOM的左上角距离。
3539482715-59feee130a8fe_articlex.jpg
type: 触发事件的类型

target:事件源,操作的是哪个元素,哪个元素就是事件源,在不兼容的浏览器中可以使用srcElement获取

preventDefault:用来阻止默认行为的方法,在不兼容的浏览器中通过使用ev.returnValue = false来实现。
stopPropagation:阻止冒泡传播,不兼容的浏览器中用ev.cancelBubble=true也可以阻止默认行为。

4.事件流

4.1 事件流模型

事件的传播机制分为三个阶段

  1. 1.捕获阶段:从最外层向最里层事件源依次进行查找(目的是为了冒泡阶段事先计算好传播的层级路径),将该层级路径存储于event对象的path属性中。CAPTURING_PHASE: 1
  2. 2.目标阶段:当前元素的相关事件行为触发。AT_TARGET: 2

3.冒泡阶段:触发当前元素的某一事件行为,不仅自身的行为被触发,它所有的祖先元素(一直到window)相关的事件行为都会被依次触发。BUBBLING_PARSE:3

4.2 addEventListener(type, listener, options)

options:

  • capture: Boolean,表示 listener 会在该类型的事件捕获阶段传播到该 EventTarget 时触发,默认值为false,冒泡阶段触发。
  • once: Boolean,表示 listener 在添加之后最多只调用一次。如果是 true, listener 会在其被调用之后自动移除。
  • passive: Boolean,设置为true时,表示 listener 永远不会调用 preventDefault()。如果 listener 仍然调用了这个函数,客户端将会忽略它并抛出一个控制台警

4.3 mouseenter/mouseleave vs mouseover/mouseout

mouseenter/mouseleave事件默认不会触发事件冒泡
mouseover/mouseout默认会触发事件冒泡

5. 事件委托

5.1 原理

  • 基于事件的冒泡传播机制完成
  • 如果一个容器中的很多子元素都要在触发某一事件的时候做一些事情(原始方案:遍历循环子元素,每一个元素都进行单独的事件绑定),基于事件委托的实现:只需要给当前容器的某一事件绑定方法,这样不论是触发后代中哪一个元素的事件,由于冒泡的传播机制,当前容器绑定的方法都会被触发执行。
  • 在绑定方法内部,通过ev.target或ev.srcElement获取事件源。得到当前真正操作的元素。

5.2 意义

  1. 基于事件委托的实现,比单独绑定性能更好
  2. 某些业务场景只能用事件委托来处理。比如说数据是动态从服务器获取的,事先无法进行绑定,这样只能绑定给容器。