主要内容:
1.事件流
2.事件注册
3.事件对象
4.事件分类
5.事件代理
什么是DOM事件?
点击一个DOM元素
键盘按下一个键
输入框输入内容
页面加载完成
1.事件流
DOM事件流经历的三个阶段(w3c标准):
1.捕获阶段(capture phase):从顶层的window到 事件触发节点的父节点。
2.触发阶段/目标阶段(target phase):事件触发节点。
3.冒泡阶段(bubble phase):从当前时间节点的父节点 到 顶层的window对象。
注意:
1.w3c定义的这三个阶段,也不是所有的浏览器都实现的。比如:在IE的低版本里面就没有『捕获过程』,只有『触发』和『冒泡』过程。
2.DOM事件中也不是全部都有这三个过程,有些事件是没有冒泡的,比如: 『页面load事件』就没有冒泡。
关于『事件流』还可以参考(英文): https://www.w3.org/TR/uievents/#dom-event-architecture
2.事件的注册与触发
2.1 事件注册
2.2 取消事件注册
2.3 事件触发
其主体都是一个『DOM元素』
2.1 事件注册
eventTarget.addEventListener(type,listener[,useCapture]);
addEventListener方法时w3c规定的。三个参数:
参数名 | 可选参数 | 描述 |
type | 事件类型。 | |
listener | 事件处理函数。 | |
useCapture | 可选 | 是否是『捕获过程』。 默认情况下DOM事件里面处理的是『冒泡过程』,只有把 useCapture 设为 true 时,它才会处理『捕获过程』 |
举个栗子:
var elem=document.getElementById('div1'); var clickHandler = function(event){ //TODO } elem.addEventListener('click',clickHandler,false);
2.2 取消事件注册
eventTarget.removeEventListener(type,listener[,useCapture])
举个栗子:
elem.removeEventListener('click',clickHandler,false);//w3c规范 elem.onclick=null;//通常不建议用这种方式
2.3 事件触发
事件触发其实有很多方式,比如『点击元素』『按下按键』『程序代码触发 』,这里只讲 『程序代码触发』。
如何用程序代码触发呢? w3c中规定了这样的API
eventTarget.dispatchEvent(type); //在DOM对象上,通过 dispathEvent 传入一个 事件类型 就可以触发。
浏览器兼容性(IE6,7,8),
我们再前面讨论的都是 w3c标准规定的,而有些厂商并没有按照 w3c标准。那么我们在平时编程中,
遇到低版本的 IE浏览器,应当怎么办呢? 实际上这些不遵循w3c标准的浏览器厂商也规定了自己的 事件注册,事件取消,事件触发的API。这就是需要我们在平时编程当中做一些兼容。
在 IE的低版本中(IE6、7、8)
事件注册与取消
--attchEvent/detachEvent 注册事件/取消事件
事件触发
--fireEvent(e)
no capture 在IE低版本中,是不存在『捕获阶段』的。
浏览器兼容性
注册事件
var addEvent = document.addEventListener ?
//w3c
function(elem,type,listener,useCapture){ elem.addEventListener(type,listener,useCapture); }: //IE 6,7,8
function(elem,type,listener,useCapture){ elem.attachEvent('on'+type,listener); };
取消事件
var delEvent = document.removeEventListener ? //w3c
function(elem,type,listener,useCapture) { elem.removeEventListener(type,listener,useCapture); }: //IE 6,7,8
function (elem,type,listener,useCapture){ elem.detachEvent('on'+type,listener); };
参考资料:
http://www.w3.org/TR/uievents/
https://developer.mozilla.org/zh-CN/docs/Web/API/EventTarget
3.事件对象
DOM元素注册事件,取消事件注册 ,以及触发事件。那么『事件对象』是什么呢?
当事件被触发时,会调用这个事件处理函数,浏览器引擎会传入一些信息,那么这个信息就代表当前事件的一些状态,这个就是事件的对象。
我们在编程过程中,会用到事件对象中的一些属性和方法。
举个栗子(w3c):
左图中,event 就是事件对象,当我用鼠标点击元素时,那么可能这个事件对象中包含了鼠标的位置,x,y坐标、
键盘上的shift键有没有被按下去、等等这样一些信息都可以在事件对象中找到。
IE低版本,事件对象的兼容处理
3.1 事件对象的属性和方法
事件有很多种类型,每一种不同类型的事件是在处理不同的场景,当然这些处理不同场景的事件对象中包含的信息也就不太一样。所以我们将属性和方法时,分为 『通用的』『个性的』。
事件对象通用的属性和方法
属性
属性名 | 描述 | 举个栗子 |
type | 事件类型 | click |
target(srcElement) | 事件触发的节点 | |
currentTarget | 当前处理事件节点的函数。 当我们要给<a>注册一个事件的时候,我们可以不注册到<a>上面,而直接注册到<a>的父节点上面,因为当事件冒泡到<a>的父节点时,我仍然可以处理这个事件。 当我们把事件注册到<a>的父节点时,那么curreTarget就是父节点。只有当事件处于目标阶段时,target才和currentTarget的值是一样的。 |
方法
方法名 | 描述 | 举个栗子 |
w3c的 stopPropagation IE低版本的 event.cancelBubble=true |
阻止传播。 有时,我们不想让事件再冒泡上去了,我们就需要调用这样的一个方法。 |
比如我在document这个节点就处理了这个事件,如果我不想让事件传给window节点的话,这时就需要阻止传播。 |
w3c的 Event.preventDefault() IE低版本的 Event.returnValue=false |
阻止默认行为 默认行为: 当我打开一个连接时,连接就会被打开。 当我双击一段文字时,这段文字就会被选中。 这些都是浏览器中定义的默认行为,但是有时候我们却不想按照默认的做,而是做一些其他操作,比如: 当我点击一个连接时,这个连接不会被打开。 |
只要我在事件处理函数中调用了这个方法,那么他的默认行为就会被阻止。 |
stopImmediatePropagation | 做了两个事情: 1.阻止事件向父节点传播 2.阻止当前节点的后续事件(所有在被阻止的事件 后面 注册的事件 不会被触发) |
|
4.事件分类
w3c对事件做的分类,每一种分类里面都定义了一些事件。
MouseEvent
事件类型 | 是否冒泡 | 元素 | 默认事件 | 元素例子 |
click | YES | Element | focus/activation | div |
dbclick | YES | Element | focus/activation | div |
mousedown | YES | Element | drag/scroll text selection |
div |
mousemove | YES | Element | None | div |
mouseout | YES | Element | None | div |
mouseover | YES | Element | None | div |
mouseup | YES | Element | context menu | div |
mouseenter | NO | Element | None | div |
mouseleave | NO | Element | None | div |
MouseEvent对象
属性
clientX--点到 浏览器 左侧的距离
clientY--点到 浏览器 顶部的距离
screenX--点到 屏幕 左侧的距离
screenY--点到 屏幕 顶部的距离
ctrlKey,shiftKey,altKey,metaKey
当MouseEvent事件被触发的时候,如果 键盘中的 Ctrl键 是按下去的,则 ctrlKey的值为true, 否则为false。
button(0,1,2)
当MouseEvent事件被触发的时候,当前按下的鼠标是 左键-0 中间键-1 右键-2
MouseEvent顺序
鼠标事件是非常灵敏的,在鼠标移动的时候实际上会触发很多mousemove的事件,在移动的过程当中会有很多鼠标事件的产生。那么这些事件之间到底是怎么样的顺序?
举个栗子:
『 从元素A上方移过 』
mousemove—>mouseover(A)—>mouseenter(A)—>mousemove(A)—>mouseout(A)—>mouseleave(A)
『 点击元素 』
mousedown—>[mousemove]—>mouseup—>click
注意:是在鼠标键弹起时触发的click
实例: 拖拽div
WheelEvent 鼠标滚轮
属性
deltaMode
deltaX
deltaY
deltaZ
FocusEvent 焦点事件
事件类型 | 是否冒泡 | 元素 | 默认事件 | 元素例子 | 描述 |
blur | NO | Window、Element | None | window、input | 当元素失去焦点时 |
focus | NO | Window、Element | None | window、input | 当元素获得焦点时 |
focusin | NO | Window、Element | None | window、input | 当元素即将获得焦点时(在获得焦点之前) |
focusout | NO | Window、Element | None | window、input | 当元素即将失去焦点时(在失去焦点之前) |
属性
relatedTarget 当一个元素失去焦点时,另外一个元素就会获得焦点。 relatedTarget就是 紧接着获得焦点的那个元素。
InputEvent 输入事件
当在输入框中输入内容时,会不断的触发事件
事件类型 | 是否冒泡 | 元素 | 默认事件 | 元素例子 | 描述 |
beforeinput | YES | Element | update DOM Element | input | 此时输入框还没有值 |
input | YES | Element | None | input |
KeyboardEvent 键盘事件
事件类型 | 是否冒泡 | 元素 | 默认事件 | 元素例子 |
keydown | YES | Element | beforeinput/input focus/blur | div,input |
keyup | YES | Element | None | div,input |
属性
key - 按下的功能键?数字键
code
ctrlKey、shiftKey、altKey、metaKey
repeat 持续按一个键不松开,repeat的值就是 true
keyCode
charCode
which