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 相关文章推荐
javascript引用对象的方法代码
Aug 13 Javascript
File文件控件,选中文件(图片,flash,视频)即立即预览显示
Apr 09 Javascript
JavaScript 计算图片加载数量的代码
Jan 01 Javascript
13 个JavaScript 性能提升技巧分享
Jul 26 Javascript
获取表单控件原始(初始)值的方法
Aug 21 Javascript
JS中的form.submit()不能提交表单的错误原因
Oct 08 Javascript
jQuery的remove()方法使用详解
Aug 11 Javascript
Javascript 计算字符串在localStorage中所占字节数
Oct 21 Javascript
Bootstrap页面标题Page Header的实现方法
Mar 22 Javascript
使用webpack搭建react开发环境的方法
May 15 Javascript
vue点击自增和求和的实例代码
Nov 06 Javascript
vue3.0中友好使用antdv示例详解
Jan 05 Vue.js
使用微信小程序开发前端【快速入门】
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函数分享之curl方式取得数据、模拟登陆、POST数据
2014/06/04 PHP
php将access数据库转换到mysql数据库的方法
2014/12/24 PHP
详解Yii2 之 生成 URL 的方法
2017/06/16 PHP
通用于ie和firefox的函数 GetCurrentStyle (obj, prop)
2006/12/27 Javascript
JavaScript基本对象
2007/01/11 Javascript
xml 与javascript结合的问题解决方法
2007/03/24 Javascript
jQueryUI写一个调整分类的拖放效果实现代码
2012/05/10 Javascript
jQuery DOM删除节点操作指南
2015/03/03 Javascript
JavaScript获取当前网页标题(title)的方法
2015/04/03 Javascript
jquery实现的横向二级导航效果代码
2015/08/26 Javascript
js制作支付倒计时页面
2016/10/21 Javascript
Bootstrap3 多个模态对话框无法显示的解决方案
2017/02/23 Javascript
对于input 框限定输入值为浮点型的js代码
2017/09/25 Javascript
利用JS测试目标网站的打开响应速度
2017/12/01 Javascript
Javascript中从学习bind到实现bind的过程
2018/01/05 Javascript
详解nodejs 开发企业微信第三方应用入门教程
2019/03/12 NodeJs
vue使用axios实现excel文件下载的功能
2020/07/16 Javascript
python实现用户登陆邮件通知的方法
2015/07/09 Python
Python基础篇之初识Python必看攻略
2016/06/23 Python
人机交互程序 python实现人机对话
2017/11/14 Python
Python跨文件全局变量的实现方法示例
2017/12/10 Python
Python实现拷贝/删除文件夹的方法详解
2018/08/29 Python
Django之使用celery和NGINX生成静态页面实现性能优化
2019/10/08 Python
python实现超级马里奥
2020/03/18 Python
Python flask框架如何显示图像到web页面
2020/06/03 Python
Python实现一个优先级队列的方法
2020/07/31 Python
CSS3制作缩略图的详细过程
2016/07/08 HTML / CSS
IE10 Error.stack 让脚本调试更加方便快捷
2013/04/22 HTML / CSS
工程预算与管理应届生求职信
2013/10/06 职场文书
公司市场部岗位职责
2013/12/02 职场文书
化学教育专业自荐信
2014/07/04 职场文书
售房协议书范本2014
2014/10/23 职场文书
部队个人年终总结
2015/03/02 职场文书
联谊活动总结范文
2015/05/09 职场文书
2015年学校心理健康教育工作总结
2015/05/11 职场文书
Window server 2012 R2 AD域的组策略相关设置
2022/04/28 Servers