Event 事件
事件是你正在编程的系统中发生的事情,系统会告诉你有关这些事件的信息,以便你的代码能够对它们做出反应。
什么是事件
当事件发生时,系统产生(或“触发”)某种信号,并提供一种机制,当事件发生时,可以自动采取某种行动(即运行一些代码)。事件是在浏览器窗口内触发的,并倾向于附加到驻留在其中的特定项目。这可能是一个单一的元素,一组元素,当前标签中加载的 HTML 文档,或整个浏览器窗口。有许多不同类型的事件可以发生。
例如:
- 用户选择、点击或将光标悬停在某一元素上。
- 用户在键盘中按下某个按键。
- 用户调整浏览器窗口的大小或者关闭浏览器窗口。
- 网页结束加载。
- 表单提交。
- 视频播放、暂停或结束。
- 发生错误。
提示
为了对一个事件做出反应,你要给它附加一个事件处理器。这是一个代码块,在事件发生时运行。当这样一个代码块被定义为响应一个事件而运行时,我们说我们在注册一个事件处理器。
注意:web 事件不是 JavaScript 语言的核心——它们被定义成内置于浏览器的 API
事件对象的额外属性
大多数事件对象都有一套标准的属性和方法,请参阅 Event 对象参考,以获得完整的列表。
事件对象
有时候在事件处理函数内部,你可能会看到一个固定指定名称的参数,例如 event、evt 或 e。这被称为事件对象,它被自动传递给事件处理函数,以提供额外的功能和信息
- event 就是一个事件对象,写道我们的侦听函数的小括号里面,当形参来看
- 事件对象只有有了事件才会存在,他是系统给我们自动创建的,不需要我们传递参数
- 事件对象是我们的事件的一系列相关数据的集合,比如鼠标点击里面就包含了鼠标的相关信息
- 这个事件对象我们可以自己命名,比如 event、evt 、e 等
- 事件对象也有兼容性问题。 IE 6、7、8 通过 window.event 实现
事件对象常见属性和方法
事件对象属性方法 | 说明 |
---|---|
e.target | 返回触发事件的对象 标准 |
e.type | 返回事件的类型,比如 click、mouseover 等,不带 on |
e.preventDefaule() | 该方法阻止默认事件(默认行为)标准 ,比如不让链接跳转 |
e.stopPropagation() | 阻止冒泡,标准 |
DOM 事件流
事件流描述的是从页面中接收事件的顺序。通常,一个事件会从父元素开始向目标元素传播,然后它将被传播回父元素。
事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即 DOM 事件流。包括以下三个阶段:
- 事件捕获阶段
- 处于目标阶段
- 事件冒泡阶段
我们知道,在 dom 模型中,html 是多层次的,当一个 html 元素上产生事件时,该事件会在 dom 树元素节点之间按照特定的顺序去传播。传播路径的每一个节点,都会收到这个事件,这就是 dom 事件流。当事件发生后,就会从内向外逐级传播,因为事件流本身没有处理事件的能力,所以,处理事件的函数并不会绑定在该事件源上。例如我们点击了一个按钮,产生了一个 click 事件,click 事件就会开始向上传播,一直到到处理这个事件的代码中。
事件捕获
事件从最不精确的对象(document 对象)开始触发,然后到最精确(也可以在窗口级别捕获事件,不过必须由开发人员特别指定)。
事件捕获默认是禁用的,你需要在 addEventListener() 的 capture
选项中启用它。
目标阶段
当到达目标元素之后,执行目标元素该事件相应的处理函数。如果没有绑定监听函数,那就不执行。
事件冒泡
事件按照从最特定的事件目标到最不特定的事件目标(document 对象)的顺序触发,当一个元素接收到事件的时候会把他接收到的事件传给自己的父级,一直到 window 。
事件委托
只操作了一次 DOM ,提高了程序的性能。
事件委托的原理
不给每个子节点单独设置事件监听器,而是设置在其父节点
上,然后利用冒泡
原理设置每个子节点。
例如: 给 ul 注册点击事件,然后利用事件对象的 target 来找到当前点击的 li ,然后事件冒泡到 ul 上, ul 有注册事件,就会触发事件监听器。
为什么用事件委托
在 JavaScript 中,添加到页面上的事件处理程序数量将直接关系到页面的整体运行性能
,因为需要不断的操作 dom,那么引起浏览器重绘和回流
的可能也就越多,页面交互的事件也就变的越长,这也就是为什么要减少 dom 操作
的原因。
每一个事件处理函数,都是一个对象,那么多一个事件处理函数,内存中就会被多占用一部分空间。如果要用事件委托,就会将所有的操作放到 js 程序里面,只对它的父级(如果只有一个父级)这一个对象进行操作,与 dom 的操作就只需要交互一次
,这样就能大大的减少与 dom 的交互次数
,提高性能
例子
需求:鼠标放到 li 上,对应的 li 背景颜色变为灰色
<ul>
<li>111</li>
<li>222</li>
<li>333</li>
</ul>
2
3
4
5
普通实现: 给每个 li 都绑定一个事件让其变灰
$('li').on('mouseover', function () {
$(this).css('background-color', 'gray').siblings().css('background-color', 'white')
})
2
3
在这段代码结束以后,我们动态的给 ul 又增加了一个 li,那么新增的这个 li 是不带有事件的,如果有无数个 li 结点,我们的 dom 是吃不消的
使用事件委托实现
js 中事件是会冒泡的,所以 this 是可以变化的,但 event.target 不会变化,它永远是直接接受事件的目标 DOM 元素
利用事件冒泡 只指定 ul 的事件处理 就可以控制 ul 下的所有的 li 的事件
$('ul').on('mouseover', function (e) {
$(e.target).css('background-color', 'gray').siblings().css('background-color', 'white')
})
2
3
第一步:
给父元素绑定事件
给元素 ul 添加绑定事件,绑定 mouseover 事件设置 css(也可通过 addEventListener 为点击事件 click 添加绑定)
第二步:
监听子元素的冒泡事件
这里默认是冒泡,点击子元素 li 会向上冒泡
第三步:
找到是哪个子元素的事件
通过匿名回调函数的参数 e 用来接收事件对象,通过 target 获取触发事件的目标(可以通过判断 target 的类型来确定是哪一类的子元素对象执行事件)