JavaScript学习--事件冒泡、事件捕获、事件代理
学习《JavaScript高级程序设计(第3版)》
事件流
事件流描述的是从页面中接收事件的顺序。然而,但是当时的两大浏览器IE和Netscape团队的事件流分别是事件冒泡流和事件捕获流。
如果你点击了按钮,他们都认为点击事件不仅仅发生在按钮上。换句话说,点击了按钮的同时,你也点击了按钮的容器元素,甚至也点击了整个页面。
事件冒泡
IE的事件流叫做事件冒泡,即事件开始时由最具体的元素接收,然后逐级向上传播到较为不具体的节点。
例如:
<!DOCTYPE html>
<html>
<head>
<title>Event Bubbling Example</title>
</head>
<body>
<div id="myDiv">Click me!</div>
</body>
</html>
当你点击了页面中的<div>元素,那么这个click事件会按照如下的顺序传播:
(1)<div>
(2)<body>
(3)<html>
(4)document
即DOM事件沿DOM树向上传播。现代所有的浏览器都支持事件冒泡,但是IE5.5版本及之前的版本会跳过<html>元素。IE9、FireFox、Chrome和Safari则将事件一直冒泡到window。
事件捕获
事件捕获和事件冒泡的过程相反。即从不太具体的节点更早接收到事件,最具体的节点最慢收到事件。前面这个例子的顺序在事件传播中为:
(1)document
(2)<html>
(3)<body>
(4)<div>
事件捕获的用意在于事件到达预定目标之前捕获它。
虽然事件捕获是Netscape Communicator 唯一支持的事件流模型,但IE9、Safari、Chrome、Opera和FireFox目前都支持这种事件流模型。尽管DOM2级事件规范要求事件应该从document对象开始传播,但是这些浏览器都是从window对象开始捕获事件的。
建议使用事件冒泡,特殊需要时再使用事件捕获。
DOM2事件流
“DOM2级事件”规定事件流包括3个阶段:事件捕获阶段、处于目标阶段、事件冒泡阶段。事件捕获为截获事件提供了机会,事件冒泡对事件作出响应。结果就是有两个机会在目标对象上面操作事件。
事件委托/事件代理
在JavaScript中,添加到页面上的事件处理程序数量将直接关系到页面的整体运行性能。
- 每个函数都是对象,都会占用内存;内存中的对象越多,性能就越差。
- 必须事先指定所有事件处理程序而导致的DOM访问次数,会延迟整个页面的交互就绪事件。
- 对“事件处理程序过多”的问题的解决方案就是事件委托。
事件委托利用了事件冒泡,即指定一个事件处理程序,就可以管理某一类型的所有事件。
例如,由于click事件会一直冒泡到document层次,也就是说,我们可以为整个页面指定一个onclick事件处理程序,而不必给每个可单击的元素分别添加事件处理程序,只需要在DOM树中尽量最高的层次上添加一个事件处理程序。
例子如下:
<ul>
<li id = "gosomewhere">go somewhere</li>
<li id = "dosomething">do something</li>
<li id="sayHi">say Hi</li>
</ul>
var list = document.getElementById("mylinks");
EventUtil.addhamdle(list,'click',function(event){
// 获取这个事件
event = EventUtil.getEvent(event);
// 获取事件目标
var target = EventUtil.getTarget(event);
switch(target.id) {
case "dosomething":
document.title = "i changed the document's title";
break;
case "gosomewhere":
location.href = "http://xxx.com";
case "sayHi" :
alert('hi');
break;
}
})
由于点击<li>元素都会冒泡到上级元素<ul>,我们为<ul>元素添加一个onclick事件处理程序,即单击事件最终会被这个函数处理。
这种技术占用的内存更少。所有用到按钮的事件都适合采用事件委托技术。
如果可行的话,可以考虑给document对象添加一个事件处理程序,用以处理页面上发生的某种特定类型的事件。该方式的好处在于:
- document对象很快就被访问,而且在页面生命周期的任何时点上为它添加事件处理程序(无须等待DOMContentLoaded或load事件)。换句话说,只要可单击的元素呈现在页面上,就可以立即具备适当的功能。
- 在页面中设置事件处理程序所需的事件更少。只需要一个事件处理程序所需的DOM引用更少,所花的事件也更少。
- 整个页面占用的内存空间更少,能够提升整体性能。
- 未来机器人大脑将获取互联网知识自我学习
- 【架构拾集】: Android 移动应用架构设计
- Dore 混合应用框架 —— 基于 React Native 的混合应用迁移方案
- Android6.0源码分析之View(二)--measure Android6.0源码分析之View(一)
- 程序员,2017年你的技能树上增加了哪些新技能?
- Android6.0源码分析之View(一)
- 2017 年,我挖的那些开源软件坑
- Android6.0蓝牙开发中获取附近低功耗蓝牙设备结果权限问题分析
- 我的技术投资策略:如何决定学习哪一个新技术的?
- 我的技术投资策略:如何决定学习哪一个新技术的?
- Android6.0源码之蓝牙研究汇总(一)--from初学者
- Android6.0蓝牙协议之OPP
- 简单直白教你理解Java中四大引用强引用,软引用,弱引用,虚引用
- ubuntu系统上配置git
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- BigData--Hadoop2.x新特性之HA
- 前端踩坑系列《四》
- BigData--Hadoop技术
- TensorFlow2.X学习笔记(8)--TensorFlow高阶API之构建模型、训练模型
- dotnet 使用 AsyncQueue 创建高性能内存生产者消费者队列
- TensorFlow2.X学习笔记(7)--TensorFlow中阶API之losses、metrics、optimizers、callbacks
- 前端须知的 Cookie 知识小结
- TensorFlow2.X学习笔记(6)--TensorFlow中阶API之特征列、激活函数、模型层
- sortable.js——Vue 数据更新问题
- 【项目实战】环境搭建
- TensorFlow2.X学习笔记(5)--TensorFlow中阶API之数据管道
- TensorFlow2.X学习笔记(4)--TensorFlow低阶API之AutoGraph相关研究
- TensorFlow2.X学习笔记(3)--TensorFlow低阶API之张量
- TensorFlow2.X学习笔记(2)--TensorFlow的层次结构介绍
- 深入浅出 Vue 中的 key 值