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 相关文章推荐
在textarea中显示html页面的javascript代码
Apr 20 Javascript
理解Javascript_07_理解instanceof实现原理
Oct 15 Javascript
javascript针对DOM的应用分析(二)
Apr 15 Javascript
fckeditor粘贴Word时弹出窗口取消的方法
Oct 30 Javascript
jQuery插件Slider Revolution实现响应动画滑动图片切换效果
Jun 05 Javascript
Spring Boot+AngularJS+BootStrap实现进度条示例代码
Mar 02 Javascript
基于百度地图api清除指定覆盖物(Overlay)的方法
Jan 26 Javascript
详解Vue打包优化之code spliting
Apr 09 Javascript
vue.extend实现alert模态框弹窗组件
Apr 28 Javascript
vue + element-ui的分页问题实现
Dec 17 Javascript
Layui 动态禁止select下拉的例子
Sep 03 Javascript
vue-cli3配置favicon.ico和title的流程
Oct 27 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的历史和优缺点
2006/10/09 PHP
mysql 全文搜索 技巧
2007/04/27 PHP
深入理解PHP原理之异常机制
2010/08/21 PHP
CodeIgniter上传图片成功的全部过程分享
2013/08/12 PHP
Yii2框架制作RESTful风格的API快速入门教程
2016/11/08 PHP
PHP中类型转换 ,常量,系统常量,魔术常量的详解
2017/10/26 PHP
php无限级评论嵌套实现代码
2018/04/18 PHP
js验证表单第二部分
2006/11/25 Javascript
IE6/7/8/9不支持exec的简写方式
2011/05/25 Javascript
jquery select动态加载选择(兼容各种浏览器)
2013/02/01 Javascript
JavaScript获取当前页面上的指定对象示例代码
2014/02/28 Javascript
页面加载完后自动执行一个方法的js代码
2014/09/06 Javascript
jQuery中$(function() {});问题详解
2015/08/10 Javascript
浅谈react+es6+webpack的基础配置
2017/08/09 Javascript
基于vue监听滚动事件实现锚点链接平滑滚动的方法
2018/01/17 Javascript
详解node Async/Await 更好的异步编程解决方案
2018/05/10 Javascript
详解基于Vue,Nginx的前后端不分离部署教程
2018/12/04 Javascript
vue component 中引入less文件报错 Module build failed
2019/04/17 Javascript
详解Vue 匿名、具名和作用域插槽的使用方法
2019/04/22 Javascript
tweenjs缓动算法的使用实例分析
2019/08/26 Javascript
vue-cli3项目升级到vue-cli4 的方法总结
2020/03/19 Javascript
Ant design vue table 单击行选中 勾选checkbox教程
2020/10/24 Javascript
[01:38]DOTA2 2015国际邀请赛中国区预选赛 Showopen
2015/06/01 DOTA
Python将xml和xsl转换为html的方法
2015/03/10 Python
Python的ORM框架中SQLAlchemy库的查询操作的教程
2015/04/25 Python
Python实现的质因式分解算法示例
2018/05/03 Python
在keras 中获取张量 tensor 的维度大小实例
2020/06/10 Python
浅谈cv2.imread()和keras.preprocessing中的image.load_img()区别
2020/06/12 Python
MAC平台基于Python Appium环境搭建过程图解
2020/08/13 Python
孕妇装中的著名品牌:Isabella Oliver(伊莎贝拉·奥利弗)
2016/10/31 全球购物
方太官方网上商城:销售方太抽油烟机、燃气灶、消毒柜等
2017/01/17 全球购物
Tiqets荷兰:出售欧洲最美丽的景点和博物馆门票
2018/01/09 全球购物
OLEDBConnection和SQLConnection有什么区别
2013/05/31 面试题
应届生高等护理求职信
2013/10/12 职场文书
中专毕业生的自我鉴定
2013/12/01 职场文书
作文批改评语大全
2014/04/23 职场文书