Javascript中的DOM(三) 事件与Event对象
事件与Event对象
- 事件
- 事件的种类
- 鼠标事件
- 键盘事件
- 表单事件
- 视图事件
- 拖放事件
- 资源事件
- Event 对象
- Event对象的属性和方法
- 标准 Event 属性
- 常用方法
- Event的继承类
- MouseEvent对象
- MouseEvent对象的属性
- KeyboardEvent对象
- KeyboardEvent的常用属性
- DOM事件流
- 阻止冒泡和捕获,取消默认行为
- 注册事件监听器
- 一、普通绑定
- 原理
- 二、事件监听
- 原理
- EventTarget.addEventListener(event, function, useCapture)
- EventTarget.removeEventListener()
- EventTarget.dispatchEvent()
- 三、事件委托
- 自定义事件
- 创建自定义事件
- 事件的监听
- 事件的触发
事件
浏览器事件是DOM 中发生的任何事件,如网页完成加载,输入字段被修改,按钮被点击等等,事件可以被JavaScript 侦测到。
如果我们给可能发生的事件注册一个处理方法,即:如果发生了就怎样怎样,那么这个应对就是事件处理函数
。一旦事件发生,在事件处理函数中可以获取到一个Event对象
,其中包含着事件的信息,如事件的类型、触发此事件的元素(事件源对象
)、事件发生的时间等等。
下面的例子中页面上有个按钮(id为btn),给这个按钮注册了click事件的事件处理函数,一旦按钮被点击,就会执行事件处理函数,而在事件处理函数中,能够获取到event对象。
document.getElementById('btn').addEventListener('click',function (event) {
console.log(event);
})
通过上图可以发现event是一个MouseEvent对象,在它的原型链上能找到UIEvent和Event。
PS:event对象只在事件发生的过程中有效,为了兼容所有浏览器,如果需要event对象,最好将event作为形参传入。
事件的种类
支持哪些事件是宿主环境决定的,不同的浏览器支持的事件可能不同,未来浏览器可能还会支持更多的事件,同时我们也可以自己定义事件。
按照事件的触发方式常用的有:
鼠标事件
在Element对象上触发
事件 | 说明 |
---|---|
mousedown | 鼠标的键钮被按下。 |
mouseup | 鼠标的键钮释放弹起。 |
click | 鼠标左键(或中键)被单击,事件触发顺序是:mousedown -> mouseup -> click |
dblclick | 鼠标左键(或中键)被双击。事件触发顺序是:mousedown -> mouseup -> click -> mousedown -> mouseup -> click -> dblclick。 |
contextmenu | 弹出右键菜单,它可能是鼠标右键触发的,也可能是键盘的菜单键触发的。 |
mouseover | 鼠标移动到目标上方。 |
mouseout | 鼠标从目标上方移出。 |
mousemove | 鼠标在目标上方移动 |
键盘事件
在Document、Element上触发
事件 | 说明 |
---|---|
keydown | 在键盘上按下某个键时触发 |
keypress | 按下某个键盘键并释放时触发 |
keyup | 释放某个键盘键时触发,该事件仅在松开键盘时触发一次 |
表单事件
在HTMLFormElement上触发
事件 | 说明 |
---|---|
reset | 点击表单重置按钮时触发 |
submit | 点击表单提交按钮时触发 |
视图事件
事件 | 说明 |
---|---|
fullscreenchange (en-US) | An element was turned to fullscreen mode or back to normal mode. |
fullscreenerror (en-US) | It was impossible to switch to fullscreen mode for technical reasons or because the permission was denied. |
resize (en-US) | The document view has been resized. |
scroll (en-US) | The document view or an element has been scrolled. |
拖放事件
事件 | 说明 |
---|---|
drag | 正在拖动元素或文本选区(在此过程中持续触发,每 350ms 触发一次) |
dragend | 拖放操作结束。(松开鼠标按钮或按下 Esc 键) |
dragenter | 被拖动的元素或文本选区移入有效释放目标区 |
dragstart | 用户开始拖动HTML元素或选中的文本 |
dragleave | 被拖动的元素或文本选区移出有效释放目标区 |
dragover | 被拖动的元素或文本选区正在有效释放目标上被拖动 (在此过程中持续触发,每350ms触发一次) |
drop | 元素在有效释放目标区上释放 |
资源事件
即网页的加载与卸载等相关的事件,在window,document上触发
事件 | 说明 |
---|---|
error | 资源加载失败时。 |
abort | 正在加载资源已经被中止时。 |
load | 资源及其相关资源已完成加载。 |
beforeunload | window,document 及其资源即将被卸载。 |
unload | 文档或一个依赖资源正在被卸载。 |
更多事件类型
Event 对象
Event 对象代表事件的状态,只在事件发生的过程中才有效,其中包含着事件发生时的信息如其中发生的元素、键盘按键的状态、鼠标的位置、鼠标按钮的状态等等。
Event对象的属性和方法
标准 Event 属性
不同的浏览器中event对象的属性不尽相同,这里只记录一些标准 的Event 属性
属性 | 描述 |
---|---|
type | 事件名称 |
bubbles | 事件是否是起泡事件类型。 |
cancelable | 是否可拥可取消的默认动作。 |
currentTarget | 触发该事件的元素。 |
eventPhase | 事件传播的当前阶段 |
target | 返回触发此事件的元素(事件的目标节点)。 |
timeStamp | 返回事件生成的日期和时间 |
button | 哪个鼠标按钮被点击。 |
relatedTarget | 返回与事件的目标节点相关的节点 |
常用方法
- initEvent() 初始化新创建的 Event 对象的属性。
- preventDefault() 通知浏览器不要执行与事件关联的默认动作(阻止默认动作)。
- stopPropagation() 阻断事件流
Event的继承类
基于Event 类,DOM中还定义了一些事件的继承类,如常见的:MouseEvent
,KeyboardEvent
,FocusEvent,TouchEvent…
MouseEvent对象
通过给鼠标事件绑定处理函数,可以得到一个MouseEvent对象
MouseEvent对象的属性
属性 | 描述 |
---|---|
button | 鼠标的哪一个键触发的事件,0 鼠标左键, 1 鼠标中键, 2 鼠标右键 |
altKey | “ALT” 是否被按下。 |
shiftKey | “SHIFT” 键是否被按下 |
ctrlKey | “CTRL” 键是否被按下 |
metaKey | “meta” 键是否被按下 |
clientX | 鼠标相对于浏览器视口的水平位置 |
clientY | 鼠标相对于浏览器视口的垂直位置 |
screenX | 鼠标相对于用户屏幕的水平位置 |
screenY | 鼠标相对于用户屏幕的垂直位置 |
pageX | clientX + 横向滚动距离 |
pageY | clientY + 纵向滚动距离 |
x | clientX的别名 |
y | clientY的别名 |
图解Js event对象offsetX, clientX, pageX, screenX, layerX, x区别
KeyboardEvent对象
通过给键盘事件绑定处理函数,可以得到一个KeyboardEvent对象
KeyboardEvent的常用属性
属性 | 说明 |
---|---|
keyCode | 该属性包含键盘中对应键位的键值 |
charCode | 该属性包含键盘中对应键位的 Unicode 编码,仅 DOM 支持 |
target | 发生事件的节点(包含元素),仅 DOM 支持 |
srcElement | 发生事件的元素,仅 IE 支持 |
shiftKey | 是否按下 Shift 键,如果按下返回 true,否则为false |
ctrlKey | 是否按下 Ctrl 键,如果按下返回 true,否则为false |
altKey | 是否按下 Alt 键,如果按下返回 true,否则为false |
metaKey | 是否按下 Mtea 键,如果按下返回 true,否则为false,仅 DOM 支持 |
关于继承类以及Event 对象的属性与方法,详见:https://developer.mozilla.org/zh-CN/docs/Web/API/Event
DOM事件流
DOM事件流指从页面中接收事件的顺序,也可理解为事件在页面中传播的顺序。
传播顺序有两种类型:事件捕捉和事件冒泡。
- 冒泡型事件:事件由叶子节点沿祖先节点一直向上传递直到根节点。
- 捕获型事件:与冒泡型刚好相反,由DOM树最顶层元素一直到最精确的元素。
PS:早期的IE事件流是冒泡, 从里面往上面冒, 网景是从外部元素往内部元素捕获;w3c 采用折中的方式,制定了统一的标准——先捕获再冒泡。
DOM2规定事件流包括三个阶段,事件捕获阶段,处于目标阶段,事件冒泡阶段,首先发生的是事件捕获,为截取事件提供机会,然后是实际目标接收事件,最后是冒泡阶段,在所有的现代浏览器都实现了DOM2标准事件流。
在下图中,以body节点为例,假设点击了div元素,标准事件流将2次经过body节点:一次是捕获阶段3,一次是冒泡阶段5,这两个阶段都可以绑定事件处理函数,通常我们在冒泡阶段绑定函数。
<a href="#" id="test">链接</a>
<script type="text/javascript"> var test = document.getElementById('test'); test.addEventListener('click', function () { console.log(this.tagName+'捕获阶段') }, true); test.addEventListener('click', function () { console.log(this.tagName+'冒泡阶段') }, false); document.body.addEventListener('click', function () { console.log(this.tagName+'捕获阶段') }, true); document.body.addEventListener('click', function () { console.log(this.tagName+'冒泡阶段') },false); </script>
上例中用addEventListener函数为元素注册事件监听器,参考后面的事件监听 。
阻止冒泡和捕获,取消默认行为
阻止冒泡和捕获的目的就是阻断事件流的传播。
在html代码中,有些元素拥有自己的默认行为,如submit按钮,单击后会自动提交表单元素,如超级链接标签,单击后会自动跳转到指定的页面。
event.stopPropagation()
方法,既可以阻止事件冒泡,但是会发生默认事件。event.preventDefault()
方法,取消事件的默认动作,但会发生事件冒泡 。
这个方法通知浏览器取消执行与事件关联的默认动作。如标签的地址跳转等。return false
方法,不但可以阻断事件流,还可以取消默认行为,并且会跳出处理函数,return false之后的所有事件都不会执行。
在前面的例子中,标签有默认动作,事件冒泡后,会发生默认事件,你会看到地址栏中多了一个#,通过下面的代码可以测试一下
test.addEventListener('click', function () {
console.log(this.tagName+'冒泡阶段');
event.stopPropagation(); //阻止事件冒泡
//event.preventDefault(); //取消事件的默认动作
//return false; //会跳出处理函数,return false之后的所有事件都不会执行
}, false);
注册事件监听器
要想让 JavaScript 对用户的操作作出响应,首先要对 DOM 元素绑定事件处理函数。
DOM中的事件分为DOM0级事件,DOM2级事件,DOM3级事件。
- DOM0级事件是可以通过给元素对象的
属性
赋值的方式,绑定事件处理函数,如onclick,onkeyup,onfocus,onchange等属性,浏览器会把一些常用事件挂载到元素对象的私有属性上,让我们可以实现DOM0事件绑定。 - DOM2级是通过
addEventListener
绑定的事件 - DOM3级事件在DOM2级事件的基础上添加了更多的事件类型,也允许使用者自定义一些事件。
有三种方式可以为DOM元素注册事件处理函数。
一、普通绑定
普通绑定是DOM0级事件处理方式,浏览器会把一些常用事件挂载到元素对象的私有属性上,让我们可以实现DOM0事件绑定。
如:element.οnclick=function(){}, 注意 onclick
是属性不是事件,click
才是事件
原理
给当前元素的某一私有属性
(onXXX)赋值的过程,赋的值是一个函数。如果赋值成功浏览器会把DOM元素和赋值的函数建立关联,建立DOM元素的行为监听,当事件被触发,浏览器会把赋值的函数执行;
只有DOM元素天生拥有这个私有属性(onxxx事件私有属性),我们赋值的方法才叫事件绑定,否则属于设置自定义属性;
- 绑定的方法都是在冒泡传播阶段执行
- 在DOM0事件绑定中,只能给当前元素的某一事件行为绑定唯一一个方法,若绑定多个方法,最后一次的绑定的会替换前面的绑定。
- 移除事件绑定的时候,我们只需要给属性赋值为null;
有两种方法实现DOM0级事件绑定
1、在DOM元素中直接绑定;
2、在JavaScript代码中绑定;
下面的代码中,给两个按钮用不同的方法都绑定了事件处理函数hello
<button onclick="hello()">按钮1</button>
<button id="btn">按钮2</button>
<script type="text/javascript"> var btn=document.getElementById('btn'); var hello=function(){ console.log(event.target.innerText+'被点击了'); console.log(this); console.log(event); }; btn.onclick=hello; </script>
代码执行时,发现方法1的this指向window,方法2的this指向this指定当前元素btn
二、事件监听
用 addEventListener()来绑定事件监听函数。
原理
所有的Node对象都部署了EventTarget接口(可以接收事件的对象实现的接口),addEventListener是在其原型上定义的,调用时,浏览器会给当前元素的某个事件行为开辟一个事件池(事件队列),当我们通过 addEventListener进行事件绑定的时候,会把绑定的方法放在事件池中;
当元素的某一行为被触发,浏览器回到对应事件池中,把当前放在事件池的所有方法按序依次执行。
DOM2中,W3C规范中定义了3个事件阶段,依次是捕获阶段、目标阶段、冒泡阶段,IE9以后IE也支持了W3C规范。
EventTarget.addEventListener(event, function, useCapture)
绑定事件监听函数
- event : (必需)事件名,支持所有 DOM事件 。
- function:(必需)指定要事件触发时执行的函数。
- useCapture:(可选)指定事件是否在捕获或冒泡阶段执行。true,捕获。false,冒泡。默认false。
EventTarget.removeEventListener()
删除EventTarget中事件侦听器。
EventTarget.dispatchEvent()
将事件分派到此EventTarget。
IE7,8的绑定事件方法使用attachEvent和detachEvent绑定和解绑监听函数
使用addEventListener绑定事件,与普通绑定的不同:
- addEventListener 能添加多个事件绑定,按顺序执行。
- addEventListener绑定后则可以用 removeEvenListener 取消;普通方式绑定事件后,不可以取消。
三、事件委托
事件委托是一种监听方式,又叫事件代理,通过监听一个父元素,来给不同的子元素绑定事件,减少监听次数。
比如我们要给ul中的li绑定事件,可以用for循环绑定事件,也可以通过事件委托,给ul绑定事件,因为事件流的关系,当点击了任何一个li节点,在冒泡节点都会触发ul的绑定事件,在ul的事件委托函数中通过Event对象的target属性可以获取到用户点击的td的信息。
<ul id="ul">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
<script type="text/javascript"> var oUl = document.getElementById('ul'); var oLi = oUl.children; //传统方法 for (var i = 0; i < oLi.length; i++) { oLi[i].onclick = function () { this.style.color='red'; } } //事件代理 oUl.onclick = function (event) { event.target.style.color='red'; } </script>
自定义事件
创建自定义事件
为了能够传递数据,一般使用 CustomEvent 构造器创建自定义事件,创建时需要两个参数:
- 事件名称 字符串类型
传递的数据对象
var myEvent = new CustomEvent(‘user_event_name’, {
detail:{
title:'my event'
},
"bubbles" : true
});
PS:自定义事件默认是不冒泡的
事件的监听
EventListener是根据事件的名称(事件对象的type属性)来进行监听的。
var btn=document.getElementById('btn');
btn.addEventListener('click',function () { });
btn.addEventListener('user_event_name', function(event) {
console.log('button绑定的事件处理函数',event)
});
document.addEventListener('user_event_name',function(event){
console.log('document绑定的事件处理函数',event);
});
事件的触发
自定义的事件不是JS内置的事件,需要在JS代码中去显式地使用 dispatchEvent方法触发,这个例子中由于设置事件允许冒泡,绑定在document上的事件处理函数也会被执行。
btn.dispatchEvent(myEvent);
可以使用全局方法getEventListeners()来查看元素的事件绑定
也可以在控制台-Elements-Event listeners面板中查看元素事件绑定
还没有评论,来说两句吧...