一步步学习javascript基础篇(8):细说事件

终于学到事件了,不知道为何听到“事件”就有一种莫名的兴奋。可能是之前的那些知识点过于枯燥无味吧,说起事件感觉顿时高大上了。今天我们就来好好分析下这个高大上的东西。

可以说,如果没有事件我们的页面就只能阅读了。有了事件,我们可以通过键盘或是鼠标和页面交互了,通过我们不同的操作页面给出不同的响应。好了,开始我们今天的分析吧。

DOM0级事件处理方式

什么是DOM0级?

其实世上本来没有DOM0级,叫的人多了就有了DOM0级。

在1998 年 10 月 DOM1级规范成为 W3C 的推荐标准,在此之前的实现我们就习惯称为DOM0级,其实本是没有这个标准的。

<input type="button" value="but" id="but" />
<script type="text/javascript">document.getElementById("but").onclick = function () {alert("点击了按钮1");}document.getElementById("but").onclick = function () {alert("点击了按钮2");} 
</script>

上面代码,我们发现点击按钮时,仅仅只弹出了“点击了按钮2”。上一个定义的方法被覆盖了。这种会覆盖上一次事件定义的方式我们称为DOM0级事件。

如果我们使用Jquery来添加事件的话:

<script src="../Scripts/jquery-1.8.2.js"></script>
<input type="button" value="but" id="but" />
<script type="text/javascript">$("#but").click(function () {alert("点击了按钮1");});$("#but").click(function () {alert("点击了按钮2");});

我们会发现依次弹出了“点击了按钮1”,“点击了按钮2”,这是怎么做到的?为什么没有覆盖上一次的定义,我猜应该是使用到了DOM2级事件机制。(我没有看过Jquery的源码,暂时还看不懂)。

DOM2级事件处理方式

<input type="button" value="but" id="but" />
<script type="text/javascript">      document.getElementById("but").addEventListener("click", function () {alert("点击了按钮1");});document.getElementById("but").addEventListener("click", function () {alert("点击了按钮2");});        
</script>

如此通过元素对象的addEventListener添加的方法就是2级事件。这里需要注意,与0级事件不同的是事件名前面不能带“on”了。点击按钮弹出的结果和前面的Jquery添加方式一样。

有人可能要问了,怎么没有DOM1级事件。我能说的是没有就是没有,没有为什么。在确定DOM1级标准的时候不需要扩展事件定义机制,DOM0级的事件就够用了。

我们刚才通过2级事件添加了方法,那么如果我们想要删除其中的一个怎么办。如果是上面的那种匿名方法,我可以很明确的告诉你没办法移除。下面我们来说说可以移除的添加方式吧:

<input type="button" value="but" id="but" />
<script type="text/javascript">      document.getElementById("but").addEventListener("click", fun1);//给click事件添加方法fun1document.getElementById("but").addEventListener("click", fun2);//给click事件添加方法fun2function fun1() {alert("点击了按钮1");}function fun2() {alert("点击了按钮2");}document.getElementById("but").removeEventListener("click", fun1);//给click事件移除方法fun1
</script>

如此就通过removeEventListener方法进行移除操作了。

以上只是DOM2级的标准实现,当然除了IE这个怪胎非得当搅屎棍。在IE下,有同效的实现函数:

<input type="button" value="but" id="but" />
<script type="text/javascript">      document.getElementById("but").attachEvent("onclick", fun1, false);//给click事件添加方法fun1document.getElementById("but").attachEvent("onclick", fun2, false);//给click事件添加方法fun2function fun1() {alert("点击了按钮1");}function fun2() {alert("点击了按钮2");}document.getElementById("but").detachEvent("onclick", fun1);//给click事件移除方法fun1

注意:attachEvent() 和 detachEvent() 替换了addEventListener()和removeEventListener(),且第一个参数是事件名前面加了"on"。

DOM3级事件

可能有人觉得很奇怪,哪来的DOM3级事件啊。其实上面我们说的DOM0级和DOM2级事件说的是事件的处理方式而已,而这里说的DOM3级事件是说的在DOM3级中新增的一些事件。

至于DOM1级事件,那我就真的没听过。

DOM3级事件是在DOM2级事件的基础上重新定义了或是新增了某些事件。如鼠标事件:

DOM2有,click、mousedown、mousemove、mouseout、mouseover、mouseup
而DOM3级中却有,click、dblclick、mousedown、mouseenter、mouseleave、mousemove、mouseout、mouseover、mouseup

(其中dblclick、mouseenter、mouseleave是DOM3中新增的)
DOM3级事件实现方式可以用DOM0和DOM2级中的方式,只是新增了写事件类型。这里就不一一列举了。

事件冒泡

什么是事件冒泡?我们先来看个例子。

<div οnclick="divfun();" style="border:1px dashed red;padding:50px"><span οnclick="spanfun();" style="border: 1px dashed #00ff21; padding: 30px; "><input type="button" value="but" οnclick="butfun();" style="border: 1px dashed #0094ff" /></span>
</div>
<script type="text/javascript">function butfun() {alert("按钮被点击了");}function spanfun() {alert("span被点击了");}function divfun() {alert("div被点击了");}
</script>

一个div包了一个span,然后span里面包了一个button。我们在点击按钮的时候会先触发按钮事件,然后触发span的点击事件,然后触发div的点击事件。这就是事件冒泡。(使用DOM0级事件默认是事件冒泡方式

效果图:

示意图:

事件捕获

什么是事件捕获?其实就是事件冒泡的逆向。

那我们怎么实现这个效果呢?我们可以通过DOM2级事件。上面我们已经简单的讲解过了DOM2级事件的实现方式

通过addEventListener和removeEventListener给事件添加和删除函数。上面我们讲addEventListener的时候如果你再回头看看,我们只给了两个参数,第一个是事件名,第二个是要添加的方法,其实还有第三个参数一个布尔值用来表示事件流方向(true为事件捕获方向,false为事件冒泡方向)。那么我们完全可以通过DOM2级事件来实现事件捕获的效果,如:

<div id="mydiv" style="border:1px dashed red;padding:50px"><span id="mysapn" style="border: 1px dashed #00ff21; padding: 30px; "><input id="mybut" type="button" value="but" style="border: 1px dashed #0094ff" /></span>
</div>
<script type="text/javascript">document.getElementById("mydiv").addEventListener("click", divfun, true);document.getElementById("mysapn").addEventListener("click", spanfun, true);document.getElementById("mybut").addEventListener("click", butfun, true);function butfun() {alert("按钮被点击了");}function spanfun() {alert("span被点击了");}function divfun() {alert("div被点击了");}
</script>

效果图:

同样,我们也可以通过DOM2级事件实现事件冒泡,就上面的代码仅仅只需要把addEventListener的第三那个参数改成false就可以了,有兴趣的同学可以自己试试。

然后IE这个搅屎棍又开始不服了,我就不实现事件捕获你能把我怎么着。IE中等效实现的attachEvent的根本就没给第三个参数,所以为了兼容,我们一般只用事件冒泡(IE只支持事件冒泡)。

事件冒泡的使用

  • 取消事件冒泡

通过上面,我们知道只要点击了按钮,那么按钮的上层元素中的点击事件都会触发。那我们会想如果我TM就只想点击某个元素的时候才 触发,不想让它往上冒怎么办,请看下面:

<div id="mydiv" style="border:1px dashed red;padding:50px"><span id="mysapn" style="border: 1px dashed #00ff21; padding: 30px; "><input id="mybut" type="button" value="but" style="border: 1px dashed #0094ff" /></span>
</div>
<script type="text/javascript">//第三个参数是false,那么就是事件冒泡了document.getElementById("mydiv").addEventListener("click", divfun, false);document.getElementById("mysapn").addEventListener("click", spanfun, false);document.getElementById("mybut").addEventListener("click", butfun, false);function butfun(event) {event.stopPropagation();//在点击按钮时,取消事件冒泡alert("按钮被点击了");}function spanfun() {//这里没有取消事件冒泡,所以点击span的时候还是会继续冒泡到divalert("span被点击了");}function divfun() {alert("div被点击了");}
</script>

效果图:

您如果仔细看了效果图,那么你会发现。点击按钮的时候并没有冒泡,而点击span的时候还是冒泡了。那是因为我们代码里面在按钮事件的方法里面加了 event.stopPropagation()//取消冒泡 。

  • 事件委托

既然可以如此,我们可以在每个事件方法里面都加上取消冒泡,那么所有的元素都只实现自己的事件对应的方法了。我们发现这个事件冒泡反而把事情搞麻烦了,好好的一个元素对应一个事件干嘛要冒泡啊,还要手动去取消冒泡。既然有这个东西,它总是有它的作用的。我们看到上面我们定义事件方法时,取到了每个元素,然后给每个元素定义方法。那我们可以通过事件冒泡定义一个方法来实现吗,先看看下面的代码:

<div id="mydiv" style="border:1px dashed red;padding:50px"><span id="mysapn" style="border: 1px dashed #00ff21; padding: 30px; "><input id="mybut" type="button" value="but" style="border: 1px dashed #0094ff" /></span>
</div>
<script type="text/javascript">//第三个参数是false,那么就是事件冒泡了document.getElementById("mydiv").addEventListener("click", divfun, false);   function divfun(event) {var targetID = event.target.id if (targetID == "mybut") {alert("按钮被点击了");} else if (targetID == "mysapn") {alert("span被点击了"); } else if (targetID == "mydiv") {alert("div被点击了"); } }
</script>

 

效果图:

仔细观察的你,会发现我们点击每个元素会触发对应消息。这就是我们上面为每个元素添加方法然后取消冒泡同样的效果。那么我们再来分析下实现代码,会发现这里反而是使用了冒泡。

 event.target//返回事件的目标节点(触发该事件的节点)  var targetID = event.target.id //返回事件的目标节点的id(触发该事件的节点的Id) 

因为我们为最外面的div添加了事件的方法,所以我们在点击按钮的时候会依次触发按钮、span、div的点击事件,然按钮和span都没有定义事件方法,所以不管是点击按钮、span还是div都会冒泡到div的点击事件,然后我们就可以根据上面的target属性来得知到底是由那个节点触发的。请看示意图:

有人会这,这么麻烦有什么好处呢?我们仔细看看这个通过冒泡实现的个节点点击事件,你有没有发现我们仅仅只是通过getElementById取了一个最外层的div元素,且我们也仅仅只用了一个方法(虽然方法里面的逻辑会更加复杂点)。这只是3个元素,如果有30个呢?甚至上百个呢?我们只定义最外层的元素,这样就减少了大量的DOM引用了(这样就直接减少了检索元素需要花的时间),同时也可以减少内存的占用。直接提升了性能。(虽然很多时候我们不会这样来定义事件,我自己就很少这样来定义事件,可能是习惯问题吧。>_<

 

这是学习记录,不是教程。文中错误难免,您可以指出错误,但请不要言辞刻薄。

原文首链:http://www.haojima.net/zhaopei/531.html

本文已同步至目录索引:一步步学习javascript

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/459257.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

求1到n ,这n个整数的二进制表示比特1的个数(时间复杂度:O(n))

题目描述&#xff1a; 给定一个数字n&#xff0c;统计1&#xff5e;n之间的n个数字的二进制的1的个数 int Nums_Of_Bit_1(int num) { int* number new int[num]; int pow 1,before 1; int count 0; for(int i1; i<num; i){ if (i pow){ …

mysql支持cube_mysql聚合函数rollup和cube

一、with rollup&#xff1a;with rollup通常和group by语句一起使用&#xff0c;是根据维度在分组的结果集中进行聚合操作。——对group by的分组进行汇总。假设用户需要对N个纬度进行聚合查询操作&#xff0c;普通的groupby语句需要N个查询和N次group by操作。而rollup的有点…

域名详解

定义 是由一串用 “.” 分割的字符组成的Internet上某一台计算机或计算机组的名称&#xff0c;域名的本质是IP地址的一个映射&#xff0c;域名的目的是便于记忆和沟通的一组服务器的地址。 域名解析 域名解析的过程实际上是将域名还原为IP地址的过程 &#xff08;1&#xf…

navicat远程mysql_navicat 远程连接mysql

一、修改用户权限&#xff1a;需要手动增加可以远程访问数据库的用户。方法一(不推荐)、本地登入mysql&#xff0c;更改 "mysql" 数据库里的 "user" 表里的 "host" 项&#xff0c;将"localhost"改为"%"#mysql -u root -proo…

应用层协议:HTTP与HTTPS协议详解、二者的区别

http协议详解 1、HTTP协议&#xff1a;超文本传输协议 是一种分布式、合作式、多媒体信息系统服务&#xff0c;面向应用层的协议。是一种通用的&#xff0c;不分状态的协议。是一种请求/应答协议。1.1、HTTP/1.0和HTTP/1.1的比较 RFC 1945定义了HTTP/1.0版本。其中最著名的就…

[POJ 1330] Nearest Common Ancestors (倍增法)

题目同上篇&#xff0c;最近公共祖先。 因为没有清零tot&#xff0c;RE了好多次TAT 一定要初始化啊&#xff01;&#xff01; 1 #include<cstdio>2 #include<cstring>3 #include<queue>4 #include<iostream>5 using namespace std;6 int root,head[100…

javascript console 函数详解 js开发调试的利器 浏览:3201|更新:2014-05-30 09:27

引用地址&#xff1a;http://jingyan.baidu.com/article/e75aca855c6419142edac6c1.html一键约师傅百度师傅最快的到家服务&#xff0c;最优质的电脑清灰&#xff01;Console 是用于显示 JS和 DOM 对象信息的单独窗口。并且向 JS 中注入1个 console 对象&#xff0c;使用该对象…

链路层基本问题 : 封装成帧、差错检测、流量控制

一、封装成帧 1、MAC帧 类型字段 &#xff08;2个字节&#xff09;&#xff1a; 用来标志上一层使用的是什么协议&#xff0c;以便把收到的MAC帧的数据上交给上一层的这个协议。 数据字段 &#xff08;46-1500&#xff09;&#xff1a; 正式名称是MAC客户数据字段最小长度6…

mysql 5.7 super_MySQL 5.7 下的对super用户只读

在MySQL的主从复制场景下&#xff0c;遇上slave被意外写入数据是一件比较严重的问题&#xff0c;毕竟在一般情况下我们都希望slave仅用只读数据库&#xff0c;如果被意外写入数据可能会造成数据的不一致&#xff0c;从而导致主从的报错。因此在MySQL中可以通过设置变量参数read…

CSS 链接

2019独角兽企业重金招聘Python工程师标准>>> 不同的链接可以有不同的样式。 链接样式 链接的样式&#xff0c;可以用任何CSS属性&#xff08;如颜色&#xff0c;字体&#xff0c;背景等&#xff09;。 特别的链接&#xff0c;可以有不同的样式&#xff0c;这取决于他…

数据链路层:ARP协议详解(绝对经典)

&#xff11;、ARP协议定义&#xff1a; 地址解析协议&#xff0c;工作在数据链路层&#xff0c;在本层和硬件接口联系&#xff0c;同时向上层提供服务。IP数据包常通过以太网发送&#xff0c;以太网设备不识别32位IP地址&#xff0c;他们是以48位以太网地址传输以太网数据包的…

php pdo操作mysql_PHP操作数据库详细(PDO)

PHP 5.1 发布时将附带一个全新的数据库连接层&#xff0c;即 PHP Data Objects (PDO)。虽然 PHP 一直都拥有很好的数据库连接&#xff0c;但 PDO 让 PHP的数据库操作 达到一个新的高度。PDO可支持基本的MySQL、Microsoft SQL Server、Oracle等数据库&#xff0c;并且提供了统一…

HTTP POST请求报文格式分析与Java实现文件上传

时间 2014-12-11 12:41:43 CSDN博客原文 http://blog.csdn.net/bboyfeiyu/article/details/41863951主题 HTTP HttpComponents在开发中&#xff0c;我们使用的比较多的HTTP请求方式基本上就是GET、POST。其中GET用于从服务器获取数据&#xff0c;POST主要用于向服务器提交一些…

网络层:IP协议详解(IP协议真的得看这篇)

1、IP协议概念 IP&#xff08;Internet Protocol , 互联网协议&#xff09;主要用于互联网通信。IP协议用于将多个包交换网络连接起来&#xff0c;他在原地址和目的地址之间传输数据报&#xff0c;还提供对数据大小的重新组装功能&#xff0c;以适应不同网络的要求。 IP协议是…

传输层两大协议:TCP与UDP详解(两者的联系与区别)

一、TCP协议 1、TCP协议报文格式 TCP协议报文格式详解 2、TCP“三次握手”建立连接 位码即tcp标志位,有6种标示: SYN(synchronous建立联机) ACK(acknowledgement 确认) PSH(push传送) FIN(finish结束) RST(reset重置) URG(urgent紧急) Sequence number(顺序号码) Ac…

docker二进制安装mysql_Docker搭建MySQL读写分离主从模式 分布式数据库中间件Mycat分库分表应用...

一、MySQL读写分离主从模式1. 下载镜像docker pull mysql当前最新版本&#xff1a;mysql Ver 8.0.19 for Linux on x86_64 (MySQL Community Server - GPL)2. 启动主节点并修改配置文件docker run -it --name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD123456 mysql bash修改/…

五种I/O模型详解

1. 概念理解 在进行网络编程时&#xff0c;我们常常见到同步(Sync)/异步(Async)&#xff0c;阻塞(Block)/非阻塞(Unblock)四种调用方式&#xff1a; 同步&#xff1a; 所谓同步&#xff0c;就是在发出一个功能调用时&#xff0c;在没有得到结果之前&#xff0c;该调用就不…

存储过程 while is null_4.2 串的存储实现(2)

返回目录&#xff1a;Chilan Yu&#xff1a;《数据结构》目录链接​zhuanlan.zhihu.com4.2.2 堆串字符串包括串名与串值两部分&#xff0c;而串值采用堆串存储方式存储&#xff0c;串名用符号表存储。堆串存储方式&#xff1a;这种存储方法以一组地址连续的存储单元存放串的字符…

高光谱图像pca降维_高光谱图像的数据特性之探讨

图像是获取信息以及探知世界的重要媒介。近年来&#xff0c;传感科技与成像技术实现了跨越式发展&#xff0c;促使图像获取在质与量上均获得了显著提升。在多样化成像手段中&#xff0c;光谱成像技术是成像科技的重要组成部分&#xff0c;是人类借助光这一能量手段探测物质特性…

注册Tomcat服务为系统服务

2019独角兽企业重金招聘Python工程师标准>>> 将解压版的Tomcat服务注册为系统服务之后&#xff0c;就不用每次启动机器之后都要手动去启动"startup.bat"&#xff0c;就方便多了&#xff0c;下面就是具体步骤&#xff08;以我的机器为例&#xff0c;我的To…