DOM 事件的深入浅出(一)


Posted in Javascript onDecember 05, 2016

在项目开发时,我们时常需要考虑用户在使用产品时产生的各种各样的交互事件,比如鼠标点击事件、敲击键盘事件等。这样的事件行为都是前端DOM事件的组成部分,不同的DOM事件会有不同的触发条件和触发效果。本文就将带大家深入浅出地了解DOM事件的那些属性和方法。

首先在介绍DOM事件之前我们先来认识下DOM的不同级别。针对不同级别的DOM,我们的DOM事件处理方式也是不一样的。

DOM级别与DOM事件

DOM级别一共可以分为4个级别:DOM0级,DOM1级,DOM2级和 DOM3级,而DOM事件分为3个级别:DOM0级事件处理,DOM2级事件处理和DOM3级事件处理。如下图所示:

DOM 事件的深入浅出(一)

有人可能会问,为什么没有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级事件的基础上添加了更多的事件类型,全部类型如下:

  1. UI事件,当用户与页面上的元素交互时触发,如:load、scroll
  2. 焦点事件,当元素获得或失去焦点时触发,如:blur、focus
  3. 鼠标事件,当用户通过鼠标在页面执行操作时触发如:dbclick、mouseup
  4. 滚轮事件,当使用鼠标滚轮或类似设备时触发,如:mousewheel
  5. 文本事件,当在文档中输入文本时触发,如:textInput
  6. 键盘事件,当用户通过键盘在页面上执行操作时触发,如:keydown、keypress
  7. 合成事件,当为IME(输入法编辑器)输入字符时触发,如:compositionstart
  8. 变动事件,当底层DOM结构发生变化时触发,如:DOMsubtreeModified

同时DOM3级事件也允许使用者自定义一些事件。

DOM事件流

上文中讲到了addEventListener的第三个参数为指定事件是否在捕获或冒泡阶段执行,设置为true表示事件在捕获阶段执行,设置为true表示事件在捕获阶段执行,而设置为false表示事件在冒泡阶段执行。那么什么是事件冒泡和事件捕获呢?可以用下图来解释:

DOM 事件的深入浅出(一)

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 事件的深入浅出(二)》同时也希望多多支持三水点靠木!

Javascript 相关文章推荐
解析offsetHeight,clientHeight,scrollHeight之间的区别
Nov 20 Javascript
javascript操作excel生成报表示例
May 08 Javascript
Node.js中require的工作原理浅析
Jun 24 Javascript
javascript中substring()、substr()、slice()的区别
Aug 30 Javascript
JS实现三个层重叠点击互相切换的方法
Oct 06 Javascript
javascript中select下拉框的用法总结
Jan 07 Javascript
jQuery简单倒计时效果完整示例
Sep 20 Javascript
node.js版本管理工具n无效的原理和解决方法
Nov 24 Javascript
JS实现的找零张数最小问题示例
Nov 28 Javascript
微信小程序简单实现form表单获取输入数据功能示例
Nov 30 Javascript
浅谈react受控组件与非受控组件(小结)
Feb 09 Javascript
总结javascript三元运算符知识点
Sep 28 Javascript
使用微信小程序开发前端【快速入门】
Dec 05 #Javascript
学习vue.js表单控件绑定操作
Dec 05 #Javascript
JavaScript易错知识点整理
Dec 05 #Javascript
JS 对java返回的json格式的数据处理方法
Dec 05 #Javascript
原生js实现键盘控制div移动且解决停顿问题
Dec 05 #Javascript
bootstrap快速制作后台界面
Dec 05 #Javascript
浅谈使用splice函数对数组中的元素进行删除时的注意事项
Dec 04 #Javascript
You might like
php从右向左/从左向右截取字符串的实现方法
2011/11/28 PHP
详解PHP的Yii框架中的Controller控制器
2016/03/29 PHP
php自动载入类用法实例分析
2016/06/24 PHP
PHP正则删除HTML代码中宽高样式的方法
2017/06/12 PHP
基于PHP常用文件函数和目录函数整理
2017/08/17 PHP
php校验公钥是否可用的实例方法
2019/09/17 PHP
JObj预览一个JS的框架
2008/03/13 Javascript
JavaScript入门教程 Cookies
2009/01/31 Javascript
js 浏览器事件介绍
2012/03/30 Javascript
JS 两日期相减,获得天数的小例子(兼容IE,FF)
2013/07/01 Javascript
借助JavaScript脚本判断浏览器Flash Player信息的方法
2014/07/09 Javascript
Javascript实现通过选择周数显示开始日和结束日的实现代码
2016/05/30 Javascript
vue.js指令v-model实现方法
2016/12/05 Javascript
vue.extend与vue.component的区别和联系
2018/09/19 Javascript
微信小程序实现录制、试听、上传音频功能(带波形图)
2020/02/27 Javascript
js实现无缝轮播图
2020/03/09 Javascript
javascript实现贪吃蛇小练习
2020/07/05 Javascript
[04:45]DOTA2上海特级锦标赛主赛事第四日RECAP
2016/03/06 DOTA
[00:37]2016完美“圣”典风云人物:rOtk宣传片
2016/12/09 DOTA
Python实现查找系统盘中需要找的字符
2015/07/14 Python
Python算法输出1-9数组形成的结果为100的所有运算式
2017/11/03 Python
Python内置函数reversed()用法分析
2018/03/20 Python
Python操作MySQL数据库的方法
2018/06/20 Python
Python各种扩展名区别点整理
2020/02/27 Python
在pycharm中debug 实时查看数据操作(交互式)
2020/06/09 Python
对pytorch中x = x.view(x.size(0), -1) 的理解说明
2021/03/03 Python
美津浓巴西官方网站:Mizuno巴西
2019/07/24 全球购物
Armor Lux法国官方网站:水手服装、成衣和内衣
2020/05/26 全球购物
高级人员简历的自我评价分享
2013/11/03 职场文书
巾帼建功标兵事迹材料
2014/05/11 职场文书
宿舍标语大全
2014/06/19 职场文书
人身损害赔偿协议书格式
2014/11/01 职场文书
学校禁毒宣传活动总结
2015/05/08 职场文书
升学宴学生致辞
2015/07/27 职场文书
PHP 对接美团大众点评团购券(门票)的开发步骤
2021/04/03 PHP
教你使用Pandas直接核算Excel中快递费用
2021/05/12 Python