1 注册事件(绑定事件)
1.1注册事件概述
给元素添加事件,称为注册事件或者绑定事件。
注册事件有两种方式: 传统方式 和 方法监听注册 方式。
1) 传统注册方式
利用 on开头的事件onclick ,如<button onclick= " alert("hi~")" > </button>
。利用事件三要素注册 btn.onclick = function (){}
但是注册事件具有唯一性 :同一个元素同一个事件只能设置一个处理函数 ,最后注册的处理函数将会覆盖前面注册的处理函数。
1 | //第二个点击事件会覆盖第一个点击事件,只执行alert('hao a u'); |
2)方法监听注册方式
w3c标准推荐方式
addEventListener()它是一个方法
lE9之前的I不支持此方法,可使用attachEvevt()代替。
特点:同一个元素同一个事件可以注册多个监听器,按注册顺序依次执行。
1.2 addEventListener事件监听方式 (ie9 之后)
eventTarget . addEventListener (type, listener [, useCapture])
eventTarget . addEventListener ()
方法将指定的监听器注册到eventTarget (目标对象)上,当该对象触发指定的事件时,就会执行事件处理函数。
该方法接收三个参数:
type :事件类型字符串,比如click、mouseover , 注意这里不要带on
listener :事件处理函数,事件发生时,会调用该监听函数
useCapture :可选参数,是一个布尔值,默认是false。 学完DOM事件流后,我们再进一 步学习
1 | //先执行 alert(33);再执行alert(11); |
1.3 attachEvent事件监听方式 (不推荐 非主流 ie9之前才支持)
eventTarget.attachEvent(eventNameWithOn,callback)
eventTarget.attachEvent()
方法将指定的监听器注册到eventTarget (目标对象)上,当该对发指定的事件时,指定的回调函数就会被执行。
该方法接收两个参数:
eventNameWithOn :事件类型字符串,比如onclick、onmouseover , 这里要带on
callback: 事件处理函数,当目标触发事件时回调函数被调用
1.4 注册事件兼容性解决方案 (了解)
1 | function addEventLi stener (element, eventName, fn) { |
兼容性处理的原则:首先照顾大多数浏览器,再处理特殊浏览器
2 删除事件(解绑事件)
2.1删除事件的方式
1) 传统注册方式
eventTarget. onclick = null;
1 | divs[0].onclick = function() { |
2) 方法监听注册方式
eventTarget.removeEventListener(type,listener[, useCapture]);
不能使用匿名函数,必须要指定被监听函数的名字。
1 | divs[1].addEventListener('click', fn) // 里面的fn 不需要调用加小括号 |
eventTarget.detachEvent(eventNameWithOn,cal1back);
类似,不能使用匿名函数。
1 | divs[2].attachEvent('onclick', fn1); |
3 DOM事件流
事件流描述的是从页面中接收事件的顺序。事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即DOM事件流。比如我们给一个div 注册了点击事件:
DOM事件流分为3个阶段:
1.捕获阶段
2.当前目标阶段
3.冒泡阶段

事件冒泡: IE 最早提出,事件开始时由最具体的元素接收,然后逐级向上传播到到DOM最顶层节点的过程。
事件捕获:网景最早提出,由DOM最顶层节点开始,然后逐级向下传播到到最具体的元素接收的过程。
事件流的过程就类似于向水里扔石头,首先是一个下降的过程(捕获阶段),到达当前目标之后,会产生泡泡,从具体元素之后漂浮到水面(事件冒泡)

JS代码中只能执行捕获或者冒泡其中的一个阶段。
onclick和attachEvent只能得到冒泡阶段。
addEventListener (type, listener[, useCapture] )第三个参数如果是true ,表示在事件捕获阶段调用事件处理程序;如果是false (不写默认就是false ) , 表示在事件冒泡阶段调用事件处理程序。
实际开发中我们很少使用事件捕获,我们更关注事件冒泡。
有些事件是没有冒泡的,比如onblur、 onfocus、 onmouseenter. onmouseleave
事件冒泡有时候会带来麻烦,有时候又会帮助很巧妙的做某些事件,我们后面讲解。
捕获阶段 和 冒泡阶段
1 | //当前处于捕获阶段,document -> html -> body -> father -> son |
1 | // 冒泡阶段 son -> father ->body -> html -> document |
***4 事件对象
4.1什么是事件对象
1 | eventTarget.onclick = function (event) {} |
官方解释: event对象代表事件的状态,比如键盘按键的状态、鼠标的位置、鼠标按钮的状态。
简单理解:事件发生后,跟事件相关的一系列信息数据的集合都放到这个对象里面,这个对象就是事件对象event ,它有很多属性和方法。
比如:
1.谁绑定了这个事件。
2.鼠标触发事件的话,会得到鼠标的相关信息,如鼠标位置。
3.键盘触发事件的话,会得到键盘的相关信息,如按了哪个键。
这个event是个形参,系统帮我们设定为事件对象,不需要传递实参过去。当我们注册事件时, event 对象就会被系统自动创建,并依次传递给事件监听器(事件处理函数)。
4.2 事件对象的常见属性和方法

1)e.target 和 this 的区别
e.target返回的是触发事件的对象(元素), this 返回的是绑定事件的对象(元素)。e.target 点击了那个元素,就返回那个元素 this 那个元素绑定了这个点击事件,那么就返回谁
比如下面我们给ul 绑定了事件,那么this 就指向ul 。 我们点击的是li e.target 指向的就是 li(冒泡阶段)
1 | <ul> |
跟 this 有个非常相似的属性 currentTarget , ie678不认识
2)返回事件类型
console.log(e.type);
3) 阻止默认行为(事件):让链接不跳转 或者让提交按钮不提交
方法监听注册方式
1 | var a = document.querySelector('a'); |
传统的注册方式
1 | a.onclick = function(e) { |
5 ***阻止事件冒泡(面试)
事件冒泡:开始时由最具体的元素接受,然后逐级向上传播到DOM最顶层节点。也就是,你点击了一个元素,他的父级元素的点击事件也会自动一次发生。有时候我们是不需要这样的。
1) dom 推荐的标准 stopPropagation() 兼容性问题
2)非标准 cancelBubble ie678
1 | var son = document.querySelector('.son'); |
6 事件委托(代理、委派)
事件冒泡本身的特性,会带来的坏处,也会带来的好处,需要我们灵活掌握。程序中也有如此场景:
1 | <ul> |
点击每个 li 都会弹出对话框,以前需要给每个li注册事件,是非常辛苦的,而且访问DOM的次数越多,这就会延长整个页面的交互就绪时间。
6.1 事件委托(面试)
事件委托也称为事件代理,在jQuery里面称为事件委派。
事件委托的原理(面试): 不是每个子节点单独设置事件监听器,而是事件监听器设置在其父节点上,然后利用冒泡原理影响设置每个子节点。
以上案例:
给ul注册点击事件,因为点击 li ,事件会冒泡到 ul 上 , ul 同时有注册事件,就会触发事件监听器从而触发事件。我们还可以利用事件对象的target来找到当前点击的 li ,修改 li 的一些属性。
1 | // 事件委托的核心原理:给父节点添加侦听器, 利用事件冒泡影响每一个子节点 |
事件委托的作用
我们只操作了一次DOM ,提高了程序的性能。
7 常用的鼠标事件
7.1常用的鼠标事件
通常 mousedown -》mousemove-》mouseup是一套 按下 移动 再按下
事件 | 说明 |
---|---|
mousedown | 鼠标的键钮被按下 |
mouseup | 鼠标的键钮被释放弹起 |
click | 单击鼠标的键钮。 |
dblclick | 鼠标的键钮被按下。 |
contextmenu | 弹出右键菜单 |
mouseover | 鼠标移到目标的上方 |
mouseout | 鼠标移出目标的上方 |
mousemove | 鼠标在目标的上方移动 |
1.禁止鼠标右键菜单
contextmenu主要控制应该何时显示上下文菜单,主要用于程序员取消默认的上下文菜单。
1 | document.addEventListener('contextmenu', function(e) { |
2.禁止鼠标选中
selectstart 开始选中
1 | document.addEventListener('selectstart', function(e) { |
7.2鼠标事件对象
event对象代表事件的状态,跟事件相关的一系列信息的集合。现阶段我们主要是用鼠标事件对象MouseEvent 和 键盘事件对象KeyboardEvent。
重点记住pageX 和 pageY属性。

1 | // 鼠标事件对象 MouseEvent |
案例 - 图标随着鼠标在屏幕移动
①鼠标不断的移动,使用鼠标移动事件: mousemove
②在页面中移动,给document注册事件
③图片要移动距离,而且不占位置,我们使用绝对定位即可。
④核心原理:每次鼠标移动,我们都会获得最新的鼠标坐标,把这个x和y坐标做为图片的top和left值就可以移动图片
8 常用的键盘事件
8.1 常用键盘事件
事件除了使用鼠标触发,还可以使用键盘触发。

1.keyup 按键弹起的时候触发
1 | document.addEventListener('keyup', function() { |
2.keydown 按键按下的时候触发 , 能识别功能键 比如 ctrl shift 左右箭头啊。
1 | document.addEventListener('keydown', function() { |
3.keypress 按键按下的时候触发 不能识别功能键 比如 ctrl shift 左右箭头啊
1 | document.addEventListener('keypress', function() { |
三个事件的执行顺序 keydown – keypress – keyup
8.2 键盘事件对象
键盘事件对象KeyboardEvent, keyCode属性返回的是按下键的ASCII值。我们可以利用keycode返回的ASCII码值来判断用户按下了那个键
1 | if (e.keyCode === 65) { |
注意: onkeydown 和onkeyup不区分字母大小写, onkeypress区分字母大小写。
在我们实际开发中,我们更多的使用keydown和keyup ,它能识别所有的键(包括功能键),keypress不识别功能键,但是keyCode属性能区分大小写,返回不同的ASCII值。
案例 - 首页按下 s 键 ,光标自动定位到搜索框
①核心思路:检测用户是否按下了s键,如果按下s键,就把光标定位到搜索框里面。
②使用键盘事件对象里面的keyCode判断用户按下的是否是s键.
②使用键盘事件对象里面的keyCode判断用户按下的是否是s键
③搜索框获得焦点:使用js里面的focus()方法.
案例 - 模拟京东快递单号查询
当我们在文本框中输入内容时,文本框上面自动显示大字号的内容。

①快递单号输入内容时,上面的大号字体盒子 ( con )显示(这里面的字号更大)
②表单检测用户输入:给表单添加键盘事件
③同时把快递单号里面的值( value )获取过来赋值给con盒子( innerText )做为内容,如果快递单号里面内容为空,则隐藏大号字体盒子(con)盒子。
④注意: keydown和keypress在文本框里面的特点:他们两个事件触发的时候,字还没有落入文本框中。
⑤keyup事件触发的时候,文字已经落入文本框里面了。也就是当文字落入文本框之后,才会触发事件。