01 事件基础

121 阅读5分钟

什么是事件

事件是浏览器赋予元素的默认行为,也可以理解为事件是天生具备的,不论是否为其绑定方法,当某些行为触发的时候,相关的事件会被触发执行。

document.body.onclick = function(){} ,说法“给body绑定了事件”是错误的

MDN浏览器赋予元素的事件行为

  • 鼠标事件

click 点击事件(PC:频繁点击N次,)、单击事件(移动端:300ms内没有发生第二次点击操作,算作单击事件行为,所以click在移动端有300ms延迟)

    • dbclick 双击事件
    • contextmenu 鼠标右键点击触发
    • mousedown 鼠标按下
    • mouseup 鼠标抬起
    • mousemove 鼠标移动, 鼠标在某元素上移动时触发,即使在其子元素上也会触发
    • mouseover 鼠标滑入, 移入和移出其子元素时也会触发
    • mouseout 鼠标滑出, 移入和移出其子元素时也会触发
    • mouseenter 鼠标进入
    • mouseleave 鼠标离开
    • onwheel鼠标滚轮滚动
    • ...
  • 键盘事件
    • keydown 键盘按下
    • keyup 键盘抬起
    • keypress 长按(除了shift/Fn/CasLock键之外)
    • ...
  • 手指事件

1.Touch Event 单手指事件模型

    • touchstart 手指按下
    • touchmove 手指移动
    • touchend 手指松开

2.Gesture Event 多手指事件模型

  • 表单事件
    • focus 获取焦点
    • blur 失去焦点
    • submit 表单提交【前提:表单元素都包含在form中,并且点击的按钮是submit中】
    • reset 表单重置【前提:表单元素都包含在form中,并且点击的按钮是reset】
    • select 下拉框内容选中
    • change 内容改变
    • input 移动端中经常用的,监控文本框中的内容随着输入的改变而触发
    • ...
  • 资源事件
    • load 加载成功(window.onload/img.onload)
    • error 加载失败
    • before 资源卸载之前(window.onbeforeunload 页面关闭之前触发)
    • ...
  • CSS3动画事件
    • transitionend transition动画结束,常用
    • transitionstart transition动画开始
    • transitionrun transition动画进行中
    • ....
  • 视图事件
    • resize 元素(浏览器)大小改变
    • scroll 滚动条滚动
    • ...
  • 网络离线offline
    • offline事件被触发。并且navigator.onLine的值变为 false
  • 网络在线online
    • 当浏览器能够访问网络,且 Navigator.onLine 的值被设为 true 时,online事件会被触发
  • ,...

什么是事件绑定

给元素默认的事件行为绑定方法,这样可以在行为触发的时候,执行这个方法。

DOM0 级事件绑定

绑定语法:[元素].on[事件] =[函数]

例如:

document.body.onclick = function(){}

移除绑定:赋值为null或者其他非函数值皆可。

document.body.onclick = null

查看浏览器支持哪些DOM0事件

dir(document.body)

原理:每一个 DOM 元素对象的私有属性上都有很多类似于 “onxxx”的私有属性,给这些代表事件的私有属性赋值,就是 DOM0 事件绑定

  • 如果没有对应事件的私有属性(例如: DOMContentLoaded) 则无法基于这种办法实现事件绑定
  • 只能给当前元素的某个事件行为绑定一个方法,绑定多个方法,最后一个操作会覆盖以往的
  • 好处是执行效率快,而且开发者使用起来方便

DOM2 事件绑定

语法:[元素].addEventListener[事件], [方法], [捕获/冒泡]

document.body.addEventListener('click', fn1, false);

第三个参数是useCapture,默认是false,即冒泡

捕获:网景公司提出

冒泡:微软公司提出

移除:[元素].removeEventListener([事件], [方法], [捕获/冒泡]) 但是需要参数和绑定的时候一样

document.body.removeEventListener('click', fn1, false);

原理

基于原型链层层查找,每一个 DOM 元素都会基于__proto__,查找 EventTarget.prototype 上的 addEventListener/removeEventListener 等方法。

如:body -- HTMLBodyElement -- HTMLElement -- Element -- Node --EventTarget -- Object

基于这些方法实现事件的绑定和移除:DOM2 事件绑定采用事件池机制:

  • DOM2 事件绑定,绑定的方法一般不是匿名函数,主要目的是方便移除事件绑定的时候使用
  • 凡是浏览器提供的事件行为,都可以基于这种模式完成事件的绑定和移除(例如:window.onDOMContentLoaded 是不行的,因为没有这个私有的事件属性,但是可以 window.addEventListener('DOMContentLoaded', fn1) 这样是可以的)
  • 可以给当前元素的某个事件类型绑定多个“不同”的方法(进入到事件池),这样当事件行为触发,会从是坚持中依次(按照绑定的顺序)取出对应的方法然后执行

事件池机制

下面表格就是浏览器开辟的事件池EventQueue,每次通过addEventListener给元素绑定一个方法,就向池子注入一个方法,通过removeEventListener移除方法就从池子中移除

元素事件类型方法阶段:冒泡/捕获
bodyclickfn1false
bodyclickfn2false
bodymouseoverfn3false

DOM0和DOM2区别

  • DOM0性能优于DOM2。DOM0是给私有属性进行绑定,采用“onXXX”绑定,赋值为null解除绑定;DOM2是基于原型链层层查找,采用addEventListener进行绑定,removeEventListener进行移除;
  • DOM0局限性大。DOM2可以给元素绑定多个不同的方法,而DOM0只能给当前元素的某个事件行为绑定一个方法;若当前元素某个事件没有私有属性的话(如:DOMContentLoaded),无法绑定方法,而DOM2可以给浏览器提供的所有事件绑定方法。

document.body.onclick=function(){}是什么意思

给body的点击事件绑定方法

小常识

为什么没有DOM1事件

DOM1级由两个模块组成:DOM核心(DOM Core)和DOM HTML,没有定义事件,所以没有DOM1事件。