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 相关文章推荐
input、button的不同type值在ajax提交表单时导致的陷阱
Feb 24 Javascript
javascript 隔行换色函数代码
Oct 24 Javascript
Javascript引用指针使用介绍
Nov 07 Javascript
简介JavaScript中的sub()方法的使用
Jun 08 Javascript
CascadeView级联组件实现思路详解(分离思想和单链表)
Apr 12 Javascript
AngularJS表单详解及示例代码
Aug 17 Javascript
mpvue中配置vuex并持久化到本地Storage图文教程解析
Mar 15 Javascript
微信小程序实时聊天WebSocket
Jul 05 Javascript
vue.js提交按钮时进行简单的if判断表达式详解
Aug 08 Javascript
在Vue项目中使用jsencrypt.js对数据进行加密传输的方法
Apr 17 Javascript
如何使用JavaScript实现栈与队列
Jun 24 Javascript
详解Vue中Axios封装API接口的思路及方法
Oct 10 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处理数据库数据如何将数据返回客户端并显示当前状态
2016/02/16 PHP
PHP+Apache+Mysql环境搭建教程
2016/08/01 PHP
py文件转exe时包含paramiko模块出错解决方法
2016/08/12 PHP
PHP实现使用DOM将XML数据存入数组的方法示例
2017/09/27 PHP
Array.prototype.slice.apply的使用方法
2010/03/17 Javascript
多个jquery.datatable共存,checkbox全选异常的快速解决方法
2013/12/10 Javascript
JavaScript编写检测用户所使用的浏览器的代码示例
2016/05/05 Javascript
基于JS实现类似支付宝支付密码输入框
2016/09/02 Javascript
Angular2的管道Pipe的使用方法
2017/11/07 Javascript
详解使用element-ui table组件的筛选功能的一个小坑
2018/11/02 Javascript
Vue实现简单的拖拽效果
2020/08/25 Javascript
[05:31]DOTA2英雄梦之声_第08期_莉娜
2014/06/23 DOTA
详解Python中的条件判断语句
2015/05/14 Python
Python解析excel文件存入sqlite数据库的方法
2016/11/15 Python
Python 正则表达式匹配字符串中的http链接方法
2018/12/25 Python
Python从单元素字典中获取key和value的实例
2018/12/31 Python
python——全排列数的生成方式
2020/02/26 Python
python3通过qq邮箱发送邮件以及附件
2020/05/20 Python
在Python中字典按值排序的实现方法
2020/11/12 Python
日本运动品牌美津浓官方购物网站:MIZUNO SHOP
2016/08/21 全球购物
印度低票价航空公司:GoAir
2017/10/11 全球购物
阿联酋航空官方网站:Emirates
2017/10/17 全球购物
时尚圣经:The Fashion Bible
2019/03/03 全球购物
医院后勤自我鉴定
2013/10/13 职场文书
《邮票齿孔的故事》教学反思
2014/02/22 职场文书
《永远的白衣战士》教学反思
2014/04/25 职场文书
建筑工地门卫岗位职责
2014/04/30 职场文书
建筑安全生产目标责任书
2014/07/23 职场文书
乡镇务虚会发言材料
2014/10/20 职场文书
2014年心理健康教育工作总结
2014/12/06 职场文书
2015年化验员工作总结
2015/04/10 职场文书
大学毕业论文致谢词
2015/05/14 职场文书
自信主题班会
2015/08/14 职场文书
2016年社区“我们的节日·中秋节”活动总结
2016/04/05 职场文书
详解Node.js如何处理ES6模块
2021/05/15 Javascript
Matplotlib绘制混淆矩阵的实现
2021/05/27 Python