什么是事件
事件是浏览器赋予元素的默认行为,也可以理解为事件是天生具备的,不论是否为其绑定方法,当某些行为触发的时候,相关的事件会被触发执行。
document.body.onclick = function(){} ,说法“给body绑定了事件”是错误的
- 鼠标事件
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移除方法就从池子中移除
| 元素 | 事件类型 | 方法 | 阶段:冒泡/捕获 |
|---|---|---|---|
| body | click | fn1 | false |
| body | click | fn2 | false |
| body | mouseover | fn3 | false |
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事件。