事件 
捕获 (capture) 
事件传播有 3 个阶段:
- 捕获 (capturing)
 - 目标 (target)
 - 冒泡 (bubbling)
 

on<event> 和 addEventListener(event, func) 默认在冒泡阶段触发。
addEventListener(event, func, { capture: true }) 会使 func 在捕获阶段触发。
简写:addEventListener(event, func, true)
删除时也需要指定捕获阶段:removeEventListener(event, func, true)
事件对象属性 event.eventPhase 表示当前事件传播的阶段。
冒泡 (bubble) 
冒泡:首先触发最深层元素的处理函数,然后是父元素,依此类推直到根元素。
几乎所有事件都会冒泡,除了 focus 等少数事件。
访问触发事件的元素:
event.target:嵌套最深的直接元素this或event.currentTarget:当前冒泡到的元素,当前处理函数所在的元素
通常冒泡会以 document 对象或 window 对象结束,也可以在处理函数中手动停止冒泡。
event.stopPropagation():停止冒泡,阻止父元素的处理函数执行event.stopImmediatePropagation():停止冒泡,并阻止当前元素在当前事件上的其他处理函数执行
事件处理程序 
事件处理程序 (event handler) 是在事件触发时执行的函数,可以有多个。
addEventListener 
添加处理程序:
js
element.addEventListener(event, handler[, options]);
element.addEventListener(event, handler[, capture]);event:事件名,Stringhandler:处理函数options:once:是否触发 1 次后被移除capture:是否在捕获阶段执行处理函数passive:设为 true 表示处理函数不会调用 preventDefault()- 如果调用了,会被忽略并在控制台打印警告
 
移除处理程序:
js
element.removeEventListener(event, handler[, options]);每种事件可能绑定了多个处理函数,所以需要传入相同的函数才能正确移除。
某些事件只能使用 addEventListener,比如 DOMContentLoaded 和 transitionend。
事件的详细信息会作为 event 对象传入处理程序的第一个参数。
event 对象属性:
type:事件名,Stringtarget:触发事件的最内层元素currentTarget:执行处理程序的当前元素,与 this 相同- ...... (每种类型的事件都有自己独有的一组属性)
 
事件处理对象 
除了指定一个函数作为处理程序,还可以指定一个具有 handleEvent 方法的对象,对于复杂繁琐、代码量大的处理函数,就可以封装到一个类或对象里,从而提高可读性。
js
class Menu {
  handleEvent(event) {
    // mousedown -> onMousedown
    let method = 'on' + event.type[0].toUpperCase() + event.type.slice(1);
    this[method](event);
  }
  onMousedown() {
    elem.innerHTML = 'Mouse button pressed';
  }
  onMouseup() {
    elem.innerHTML += '...and released.';
  }
}事件类型 
鼠标事件:
clickmouseenter/mouseleavemouseover/mouseoutmousedown/mouseupcontextmenu
键盘事件:
keydown/keyup
表单事件:
submitfocus
DOM 事件:
DOMContentLoaded
CSS 事件:
transitionend