在项目开发时,我们时常需要考虑用户在使用产品时产生的各种各样的交互事件,比如鼠标点击事件、敲击键盘事件等。这样的事件行为都是前端DOM事件的组成部分,不同的DOM事件会有不同的触发条件和触发效果。本文就将带大家深入浅出地了解DOM事件的那些属性和方法。
首先在介绍DOM事件之前我们先来认识下DOM的不同级别。针对不同级别的DOM,我们的DOM事件处理方式也是不一样的。
DOM级别与DOM事件
DOM级别一共可以分为4个级别:DOM0级,DOM1级,DOM2级和 DOM3级,而DOM事件分为3个级别:DOM0级事件处理,DOM2级事件处理和DOM3级事件处理。如下图所示:
有人可能会问,为什么没有DOM1级事件处理呢?因为1级DOM标准中并没有定义事件相关的内容,所以没有所谓的1级DOM事件模型。
关于DOM级别这里不做详细的介绍,下面主要介绍下不同级别DOM中的不同事件。
1.DOM0级事件
在了解DOM0级事件之前,我们有必要先了解下HTML事件处理程序,也是最早的这一种的事件处理方式,代码如下:
<button type="button" onclick="showFn()"></button> <script> function showFn() { alert('Hello World'); } </script>
以上代码我们通过直接在HTML代码里定义了一个onclick的属性触发showFn方法,这样的事件处理程序最大的缺点就是HTML于JS强耦合,我们一旦需要修改函数名就得修改两个地方。当然其优点是不需要操作DOM来完成事件的绑定。
那么什么是DOM0级处理事件呢?DOM0级事件就是将一个函数赋值给一个事件处理属性,比如:
<button id="btn" type="button"></button> <script> var btn = document.getElementById('btn'); btn.onclick = function() { alert('Hello World'); } // btn.onclick = null; 解绑事件 </script>
以上代码我们给button定义了一个id,通过JS获取到了这个id的按钮,并将一个函数赋值给了一个事件处理属性onclick,这样的方法便是DOM0级处理事件的体现。我们可以通过给事件处理属性赋值null来解绑事件。
DOM0级事件处理程序的缺点在于一个处理程序无法同时绑定多个处理函数,比如我还想在按钮点击事件上加上另外一个函数。
2.DOM2级事件
DOM2级事件在DOM0级事件的基础上弥补了一个处理程序无法同时绑定多个处理函数的缺点,允许给一个处理程序添加多个处理函数。代码如下:
<button id="btn" type="button"></button> <script> var btn = document.getElementById('btn'); function showFn() { alert('Hello World'); } btn.addEventListener('click', showFn, false); // btn.removeEventListener('click', showFn, false); 解绑事件 </script>
DOM2级事件定义了addEventListener和removeEventListener两个方法,分别用来绑定和解绑事件,方法中包含3个参数,分别是绑定的事件处理属性名称(不包含on)、处理函数和是否在捕获时执行事件处理函数。如果我们还需要添加一个鼠标移入的方法,只需要:
btn.addEventListener('mouseover', showFn, false);
这样点击按钮和鼠标移入时都将触发showFn方法。
需要注意的是IE8级以下版本不支持addEventListener和removeEventListener,需要用attachEvent和detachEvent来实现:
btn.attachEvent('onclick', showFn); // 绑定事件 btn.detachEvent('onclick', showFn); // 解绑事件
这里我们不需要传入第三个参数,因为IE8级以下版本只支持冒泡型事件。
3.DOM3级事件
DOM3级事件在DOM2级事件的基础上添加了更多的事件类型,全部类型如下:
同时DOM3级事件也允许使用者自定义一些事件。
DOM事件流
上文中讲到了addEventListener的第三个参数为指定事件是否在捕获或冒泡阶段执行,设置为true表示事件在捕获阶段执行,设置为true表示事件在捕获阶段执行,而设置为false表示事件在冒泡阶段执行。那么什么是事件冒泡和事件捕获呢?可以用下图来解释:
1.事件冒泡
所谓事件冒泡就是事件像泡泡一样从最开始生成的地方一层一层往上冒,比如上图中a标签为事件目标,点击a标签后同时也会触发p、li上的点击事件,一层一层向上直至最外层的html或document。下面是代码示例:
<div id="box"> <a id="child">事件冒泡</a> </div> <script> var box = document.getElementById('box'), child = document.getElementById('child'); child.addEventListener('click', function() { alert('我是目标事件'); }, false); box.addEventListener('click', function() { alert('事件冒泡至DIV'); }, false); </script>
上面的代码运行后我们点击a标签,首先会弹出'我是目标事件'提示,然后又会弹出'事件冒泡至DIV'的提示,这便说明了事件自内而外向上冒泡了。
那么我们如何阻止事件冒泡呢?这里就涉及事件的Event对象中的stopPropagation方法,如下:
child.addEventListener('click', function(e) { alert('我是目标事件'); e.stopPropagation(); }, false);
加上stopPropagation方法后,我们再次点击a标签就不会触发div上的click事件了。
2.事件捕获
和事件冒泡相反,事件捕获是自上而下执行,我们只需要将addEventListener的第三个参数改为true就行。
<div id="box"> <a id="child">事件冒泡</a> </div> <script> var box = document.getElementById('box'), child = document.getElementById('child'); child.addEventListener('click', function() { alert('我是目标事件'); }, true); box.addEventListener('click', function() { alert('事件冒泡至DIV'); }, true); </script>
此时我们点击a标签,首先弹出的是'事件冒泡至DIV',其次弹出的是'我是目标事件',正好与事件冒泡相反。
总结
本文主要介绍了不同DOM级别下的事件处理程序,同时介绍了事件冒泡和捕获的触发原理和方法。熟练地使用不同级别的DOM事件并且解决相应的浏览器兼容性问题对我们的前端项目开发会很有帮助。在下篇文章中,我将给大家介绍DOM事件中Event对象的属性和方法。
以上就是本文的全部内容,希望对大家有所帮助,有兴趣的朋友可以看下《DOM 事件的深入浅出(二)》同时也希望多多支持小牛知识库!
本文向大家介绍深入浅析Node.js 事件循环,包括了深入浅析Node.js 事件循环的使用技巧和注意事项,需要的朋友参考一下 Node.js 是单进程单线程应用程序,但是通过事件和回调支持并发,所以性能非常高。 (来源于Javascript是单线程又是异步的,但是这种语言有个共同的特点:它们是 event-driven 的。驱动它们的 event 来自一个异构的平台。) Node.js 的每一个
本书从不同的视角介绍了 Node 内在的特点和结构。由首章Node 介绍为索引,涉及Node 的各个方面,主要内容包含模块机制的揭示、异步I/O 实现原理的展现、异步编程的探讨、内存控制的介绍、二进制数据。
Django简介 Django是一个高级的Python Web开发框架,它的目标是使得开发复杂的、数据库驱动的网站变得更加简单。 由于Django最初是被开发来用于管理劳伦斯出版集团旗下的一些以新闻内容为主的网站的。所以,我们可以发现在使用Django的很多网站里,都是用于作为CMS(内容管理系统)来使用的。使用Django的一些比较知名的网站如下图所示: 使用Django的网站 Django是一
当我学会如何使用Doker来发布一个容器,以及学会如何使用docker-compose来发布和管理服务时,我很惊讶Docker容器真的是一个好东西!在研究分布式系统、微服务框架时,Docker确实是一个很好的帮手。 我们通过Docker能够在单主机上模拟分布式集群环境,当然你的主机在CPU/内存/硬盘等系统资源的性能如果能够尽可能高的话,你会感到你的学习和研究过程是多么的流畅,让人心旷神怡!
Java Web,是用 Java 技术来解决相关 web 互联网领域的技术总和。web 包括:web 服务器和 web 客户端两部分。
本文向大家介绍深入浅析vue组件间事件传递,包括了深入浅析vue组件间事件传递的使用技巧和注意事项,需要的朋友参考一下 由于新工作需要用vue,所以最近接触最多的也是vue,因为之前一直在用react,所以对于vue上手还是很快的。 我也尽量找一些他们两个的异同点,除了多了一些辅助用的方法以外,最大的不同应该是对于组件间的通信,不仅有props,还有一种事件监听,也是可以通过组件间传递的。 但是,
本文向大家介绍浅入深出Vue之组件使用,包括了浅入深出Vue之组件使用的使用技巧和注意事项,需要的朋友参考一下 组件在 vue开发中是必不可少的一环,用好组件这把屠龙刀,就能解决不少问题。 组件是什么 官方的定义: 组件是可复用的 Vue 实例,并且可带有一个名字。 官方的定义已经非常简明了,组件就是一个实例。 如何使用组件 在具体编写组件实例代码前,我们先来如下几个约定: 所有组件基于单文件组件
在Android Support Library19.1版本中,Android工具小组引入了几个很酷的注解类型,供开发者在工程中使用。Support Library自身也使用这些注解,这是一个好兆头。就让我们好好研究下。 通过gradle可以很容易的把这些注解添加到我们的工程中: compile 'com.android.support:support-annotations:20.0.0' 有