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 相关文章推荐
Jquery AJAX 框架的使用方法
Nov 03 Javascript
在jQuery中 关于json空对象筛选替换
Apr 15 Javascript
js中substring和substr两者区别和使用方法
Nov 09 Javascript
jQuery实现获取table表格第一列值的方法
Mar 01 Javascript
详解用原生JavaScript实现jQuery的某些简单功能
Dec 19 Javascript
jQuery简单实现MD5加密的方法
Mar 03 Javascript
webpack构建换肤功能的思路详解
Nov 27 Javascript
Vue+SpringBoot开发V部落博客管理平台
Dec 27 Javascript
JS实现将二维数组转为json格式字符串操作示例
Jul 12 Javascript
微信小程序绑定手机号获取验证码功能
Oct 22 Javascript
Vue基于iview实现登录密码的显示与隐藏功能
Mar 06 Javascript
TypeScript 使用 Tuple Union 声明函数重载
Apr 07 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
ucenter中词语过滤原理分析
2016/07/13 PHP
PHP有序表查找之二分查找(折半查找)算法示例
2018/02/09 PHP
PHP基于curl实现模拟微信浏览器打开微信链接的方法示例
2019/02/15 PHP
PHP时间相关常用函数用法示例
2020/06/03 PHP
JQuery里选择超链接的实现代码
2011/05/22 Javascript
js拦截alert对话框另类应用
2013/01/16 Javascript
JQuery实现鼠标移动到图片上显示边框效果
2014/01/09 Javascript
jQuery.extend 函数及用法详细
2015/09/06 Javascript
Boostrap模态窗口的学习小结
2016/03/28 Javascript
javascript加载xml 并解析各节点的值(实现方法)
2016/10/12 Javascript
详解在Angularjs中ui-sref和$state.go如何传递参数
2017/04/24 Javascript
ES5 ES6中Array对象去除重复项的方法总结
2017/04/27 Javascript
JS实现仿饿了么在浏览器标签页失去焦点时网页Title改变
2017/06/01 Javascript
jQuery完成表单验证的实例代码(纯代码)
2017/09/30 jQuery
实现elementUI表单的全局验证的方法步骤
2019/04/29 Javascript
JavaScript实现简单随机点名器
2019/11/21 Javascript
vue使用require.context实现动态注册路由
2020/12/25 Vue.js
[01:00:52]2018DOTA2亚洲邀请赛 4.4 淘汰赛 EG vs LGD 第一场
2018/04/05 DOTA
用python代码做configure文件
2014/07/20 Python
详细解析Python当中的数据类型和变量
2015/04/25 Python
python3使用PyMysql连接mysql数据库实例
2017/02/07 Python
Linux(Redhat)安装python3.6虚拟环境(推荐)
2018/05/05 Python
python实现两张图片的像素融合
2019/02/23 Python
python使用参数对嵌套字典进行取值的方法
2019/04/26 Python
python获取指定日期范围内的每一天,每个月,每季度的方法
2019/08/08 Python
Django REST framework 单元测试实例解析
2019/11/07 Python
Pycharm 2020最新永久激活码(附最新激活码和插件)
2020/09/17 Python
Python定时器线程池原理详解
2020/02/26 Python
瑞典灯具和照明网上商店:Lamp24.se
2018/03/17 全球购物
Genny意大利官网:意大利高级时装品牌
2020/04/15 全球购物
德语专业求职信
2014/03/12 职场文书
啤酒节策划方案
2014/05/28 职场文书
项目合作协议书
2014/09/23 职场文书
办公经费申请报告
2015/05/15 职场文书
如何书写你的职业生涯规划书?
2019/06/27 职场文书
如何Python使用re模块实现okenizer
2022/04/30 Python