javascript中的事件
一.简介
javascript中的事件,可以理解就是在HTML文档或者浏览器中发生的一种交互操作。
本篇文章会从以下几个点去详细介绍javascript中的事件:
>> 事件处理程序
>> 事件流机制
>> 事件对象
>> 实践应用——事件委托
二.事件处理程序
事件处理程序指的是处理事件的函数,也可以称其为事件侦听器。
所以了解事件的第一步就是如何去添加或者删除事件处理程序,下面会总结几种常见的事件处理程序的添加/删除方法。
1.HTML事件处理程序
HTML事件处理程序,即直接将事件处理程序添加在HTML元素中。
一般在代码中比较常见,直接看示例。
<button onclick=“submit()”>提交</button>
这种直接在HTML中指定事件处理程序会有一个比较明显的缺点:有可能存在用户在点击按钮时,事件处理函数submit还未解析到,此时就会报错。 **2.DOM0级事件处理程序** DOM0级规定的事件处理程序是在javascript中通过给事件处理程序定义一个函数实现的。 这种方式可以为button元素添加多个事件处理函数,只不过只有最后一个会生效。 移除事件的方式也比较简单,即将事件处理程序的值设置为null。 **3.DOM2级事件处理程序** DOM2级事件中为处理事件新增了两个api,一个是添加事件api:addEventListenter;一个是移除事件api:removeEventListener。 这个两个api都可以接收三个参数: eventName 事件名称 fn 事件处理函数 booleanVal 一个布尔值,默认为false。用于指示事件处理函数在那个阶段执行(这个参数的作用会在事件流机制中说明)。 api使用示例: 关于这两个api的使用,我们需要注意几点。 首先第一点就是使用addEventListener可以添加多个事件处理程序,而且事件处理程序会按照代码添加顺序依次执行。 第二点是使用addEventListener添加的事件处理程序,只能通过removeEventListener来移除。 第三个需要注意的是使用addEventListener添加事件处理程序时,如果传递的第二个参数fn是一个匿名函数,则无法使用removeEventListener去移除。 对于第三个点中提及到的匿名函数,这个写一个简单的示例。 **4.IE事件处理程序** **对于IE8以及更早版本的IE浏览器来说,它不支持addEventListener、removeEventListener这两个api。** 它支持和这两个类似的api分别为:attachEvent和deleteEvent。 这两个api也需要接收两个参数: eventName 事件名称 fn 事件处理函数 那话不多说,写一个示例: 使用这两个api的时候也有几个注意的地方。 第一点是api的eventName参数传递,注意**是onclick而不是click**。 第二点就是使用attachEvent可以添加多个事件处理程序,而且事件处理程序会**按照代码添加的相反顺序依次执行**。 第三点是使用attachEvent添加的事件处理程序,只能通过deleteEvent来移除。 第四个需要注意的是使用attachEvent添加事件处理程序时,如果传递的第二个参数fn是一个匿名函数,则无法使用deleteEvent去移除。 其中最后两点和addEventListener/removeEventListener这两个api用法一致。 和addEventListener/removeEventListener这两个api用法有区别的就是第一点和第二点,已经用红色标记出来,使用的时候需要注意。 **注意:IE11目前已经不支持attachEvent和deleteEvent,直接在脚本中调用方法会报错。** **5.通用事件处理程序** 前面介绍了多种不同添加/移除事件处理程序的方式。 考虑到浏览器的兼容性,我们需要有一个通用的事件处理程序,以便我们进行快速的项目开发。 因此,下面就写一个简单的通用事件处理程序。 var EventUtils = { //添加事件 addEvent: function(element, eventName, fn){ if(element.addEventListener){ element.addEventListener(eventName, fn, false); }else if(element.attachEvent){ element.attachEvent('on' + eventName, fn) }else{ element.eventName \= fn; } }, //移除事件 removeEvent: function(element, eventName, fn){ if(element.removeEventListener){ element.removeEventListener(eventName, fn, false); }else if (element.deleteEvent){ element.deleteEvent('on' + eventName, fn); }else{ element.eventName \= null; } } }; (这个事件处理程序比较简单,后面内容总结完成后会将这段代码进行补充完善。) # 三.事件流机制 对于事件流专业的解释为:页面接收事件的顺序。 那对于页面接收事件的顺序,分为两种,分别是:事件冒泡(event bubbling)和事件捕获(event capturing)。 **1.事件冒泡** 事件冒泡最早是IE提出来的事件流顺序。那么它指的是事件从子元素向父元素传播。 现在我们有这样一段html文档:  当我们点击触发button元素的click事件后,会依次触发button元素、p元素、div元素、body元素和html元素的click事件。  **2.事件捕获** 事件捕获和事件冒泡是相反的顺序,即事件由父元素向子元素传播。 那还是前面的那段html文档  对于捕获型的事件流,当我们触发了button的click事件后,会依次触发html元素、body元素、div元素、p元素和button元素的clcik事件。  前面DOM2级的事件处理程序中,我们介绍了两个api:addEventListener和removeEventListener。 这两个api的接收的第三个boolean参数就是用来指定事件处理程序在那个阶段执行。 其中false值,即指定事件在冒泡阶段执行;相反指定true值,表示事件在捕获阶段执行。 而对于IE提供的两个api:attachEvent和deleteEvent,它们并不支持第三个参数,因此IE8以前的版本只支持事件冒泡的机制。 # 四.事件对象 当我们触发html文档中元素的某个事件时,事件处理程序的内部就会有一个事件对象event产生,这个对象会包含和事件相关的一些信息。 (下面说的事件对象仅限于DOM0级和DOM2级事件处理程序,IE会单独说明) 属性/方法 类型 说明 event.type String 被触发事件的类型。 比如触发button的click事件,那event.type的值就为"click"。 event.target Element 本次事件中的目标元素。 因为事件流机制的存在,当点击button时,会按照不同的顺序触发其他元素的事件,在这个过程中,被点击的button元素就是事件中的目标元素。 event.currentTarget Element 本次事件中,当前正在处理的元素。 按照事件冒泡或者捕获的顺序处理到那个元素的事件,那个元素就是当前正在处理的元素。 event.cancelable Boolean 表示是否可以取消事件的默认行为。 true:表示可以取消事件的默认行为。 event.preventDefault() Function 调用该方法可以取消事件的默认行为,但是前提是event.cancelable的值为true。 event.bubbles Boolean 表明事件是否冒泡 event.stopPropagation() Function 调用该方法可以取消事件的下一步冒泡,但前提是event.bubbles的值为true。 关于事件对象event的信息,我们一个一个来实践一下。 **1.event.type**  **2.event.target和event.currentTarget**
五.实践应用——事件委托
最后这一部分,主要是针对事件冒泡的一个应用。
我们假设有这样一个场景:有一个商品列表,点击其中某一个商品,弹框显示商品标题。同时用户可以在商品列表添加商品。
现在我们实现一下这个需求。
<html>
<head>
<meta charset=“utf-8”/>
<title>事件委托</title>
<style> li{ cursor: pointer; padding: 20px;
}
</style>
</head>
<body>
<h1>事件委托</h1>
<div class=‘box’>
<button onclick=“add()”>添加商品</button>
<div class=‘list’>
<h3>商品列表</h3>
<ul>
<li>商品1</li>
<li>商品2</li>
<li>商品3</li>
<li>商品4</li>
</ul>
</div>
</div>
<script type=“text/javascript”>
// 遍历商品列表添加点击事件
var liEle = document.getElementsByTagName(‘li’); for(var i = 0; i<liEle.length; i++){ var element = liEle[i];
element.addEventListener(‘click’, function(){
alert(this.innerHTML);
})
} // 添加商品
function add(){ var ulEle = document.getElementsByTagName(‘ul’)[0]; var liLength = document.getElementsByTagName(‘li’).length; var newLiEle = document.createElement(‘li’);
newLiEle.innerHTML = “商品”+(liLength+1);
ulEle.appendChild(newLiEle);
} </script>
</body>
</html>
我们看一下浏览器效果。
可以看到,循环li元素添加的点击事件均可以正常执行,而点击【添加商品】按钮添加的商品5,点击之后并没有click事件,因此没有弹窗显示。
这个需求实际上可以转化为这样的应用场景:事件添加个数不确定。
那么根据前面提说的事件流、事件冒泡和事件对象,我们很容易就能想到解决办法:
将click事件添加到父元素ul元素上,利用事件冒泡和event.target实现弹窗。
这个办法我们被称为事件委托机制。
下面我们代码实现一下。
(修改代码:27行-32行)
1 <html>
2 <head>
3 <meta charset=“utf-8”/>
4 <title>事件委托</title>
5 <style>
6 li{
7 cursor: pointer;
8 padding: 20px;
9 }
10 </style>
11 </head>
12 <body>
13 <h1>事件委托</h1>
14 <div class=‘box’>
15 <button onclick=“add()”>添加商品</button>
16 <div class=‘list’>
17 <h3>商品列表</h3>
18 <ul>
19 <li>商品1</li>
20 <li>商品2</li>
21 <li>商品3</li>
22 <li>商品4</li>
23 </ul>
24 </div>
25 </div>
26 <script type=“text/javascript”>
27 // 将click事件添加到父元素ul元素上,利用事件冒泡和event.target实现弹窗
28 var ulEle = document.getElementsByTagName(‘ul’)[0]; 29 ulEle.addEventListener(‘click’, function(){ 30 var target = event.target; 31 alert(target.innerHTML); 32 }) 33
34 // 添加商品
35 function add(){ 36 var ulEle = document.getElementsByTagName(‘ul’)[0]; 37 var liLength = document.getElementsByTagName(‘li’).length; 38 var newLiEle = document.createElement(‘li’); 39 newLiEle.innerHTML = “商品”+(liLength+1); 40 ulEle.appendChild(newLiEle); 41 } 42 </script>
43 </body>
44 </html>
完结!!!
如果觉得有用的话,点个赞鼓励一下~
转载请先注明出处~
最近作者新开通了一个微信公众号。
微信公众号会分享一些自己日常的东西,包括个人总结呀,吸猫日常呀,同时也会分享一些博客上的前端技术文章。
欢迎大家扫码关注~
原文链接:https://www.cnblogs.com/HouJiao/p/12309348.html
本站声明:网站内容来源于网络,如有侵权,请联系我们,我们将及时处理。