浅谈JavaScript的事件(事件处理程序)

  事件就是用户或者浏览器自身执行的某种动作。诸如click、load和mouseover,都是事件的名字。而响应某个事件的函数就叫事件处理程序。事件处理程序的名字以“on”开头,比如click事件的事件处理程序是onclick。为事件指定事件处理程序的方式有多种方式。

  • HTML事件处理程序

元素支持的事件,都可以使用与相应事件处理程序同名的HTML特性来指定。这个特性的值能支持一定的JavaScript代码。例如,在单击按钮的时候执行一些JavaScript代码。 <div id="aa" onclick="console.log('div')" style="width: 100px;">2222</div> ,当单击这个div的时候,会在浏览器的控制台中输出div。这个特性是通过JavaScript来实现的,不能在其中使用未经转义的HTML语法字符,例如和号(&)、双引号("")、单引号('')、小于号(<)或者大于号(>)。

  在HTML中定义的事件处理程序可以包含要执行的具体动作,也可以调用定义在其他页面的脚本。

1  function divClick(e){
2              var target=e.target;
3              console.log("div");
4              //stopBubble(e);
5          }

<div id="aa" onclick="divClick(event);" style="width: 100px;">2222</div>

  上面的代码中,点击div之后就会调用divClick函数。这个函数是单独定义的script脚本中的,当然也可以定义在一个外部文件中。事件处理程序中的代码,可以访问全局的方法。上面的代码中,同样可以传递event参数以及this参数。event参数能够获取事件的类型参数等,通过this能够获取点击对象本身。

1  function divClick(e){
2              //var target=e.target;
3              console.log($(e).text());//222
4              //stopBubble(e);
5          }

<div id="aa" onclick="divClick(this);" style="width: 100px;">2222</div>

  在HTML中指定事件处理程序有一定的缺点:存在一定的时差,用户可能在页面一出现就触发相应的事件,但是事件处理程序尚不具备执行的条件。上面的例子上,如果divClick函数定义在div的下方,我们在函数尚未解析之前,就点击div,这样就会导致报错。

  另一个缺点是,这样的事件处理程序的作用域链在不同的浏览器中会导致不同结果。不同JavaScript引擎遵循的标识符解析规则略有差异,很可能在访问非限定对象时出错。

  通过HTML指定事件处理程序的最后一个缺点是HTML与JavaScript代码的紧密耦合。如果要更换事件处理程序就需要改动两个地方:JavaScript和HTML。

  • DOM级事件处理程序

  通过JavaScript指定事件处理程序的传统方式是将一个函数赋值给事件处理程序属性。通过JavaScript指定事件处理程序有两个优势:简单和浏览器兼容性好。要使用JavaScript指定事件处理程序,首先必须获取一个元素的对象引用。每个元素都有自己的事件处理程序,这个属性通常是全部小写,比如onclick。

1 <div id="aa"  style="width: 100px;">2222</div>
2         <script>
3             var a=document.getElementById("aa");
4             a.onclick=function(e){
5                 var target=e.target;
6                 var text=target.innerHTML;
7                 console.log(text);//222
8             }
9         </script>

  上面的代码,通过文档对象获取了对象的引用,然后为它指定了onclick事件处理程序。e为点击事件的参数,通过该参数能够获取点击事件的对象,即target。通过对象可以进一步获取对象的属性。

1 <div id="aa"  style="width: 100px;">2222</div>
2         <script>
3             $("#aa").click(function(e){
4                 var target=e.target;
5                 var text=target.innerHTML;
6                 console.log(text);//222
7             });
8         </script>

  这段代码与上面的例子实现的是一样的效果,但是这个是通过JQuery来实现的。

  DOM2级事件处理程序定义了两个方法,用于处理指定和删除事件处理程序的操作:addEventListener和removeEventListener。所有DOM节点都包含这两个方法,并且他们接收3个参数:要处理的事件名、作为事件处理程序的函数和一个布尔值。布尔值如果为true,表示在捕获阶段执行事件处理程序,如果为false,表示在冒泡阶段调用事件处理程序。

1 <div id="aa"  style="width: 100px;">2222</div>
2         <script>
3             var a=document.getElementById("aa");
4             a.addEventListener("click",function(e){
5                 console.log(this.id);
6             },false);
7         </script>

  上面的例子通过addEventListener为元素aa添加了一个click事件。通过事件处理程序能够访问到元素,this和元素处在同一个作用域链。

  通过DOM2级可以通过添加多个事件处理程序。事件处理程序会按照添加的顺序依次触发。

1 var a=document.getElementById("aa");
2             a.addEventListener("click",function(e){
3                 console.log(this.id);
4             },false);
5             a.addEventListener("click",function(e){
6                 console.log(this.innerHTML);
7             },false);

  通过addEventListener添加的事件处理程序,可以通过removeEventListener来移除事件处理程序。但是,有时候我们会走入一个误区。

1 var a=document.getElementById("aa");
2             a.addEventListener("click",function(e){
3                 console.log(this.id);
4             },false);
5             a.removeEventListener("click",function(e){
6                 console.log(this.id);
7             },false);

  上面的代码我们使用removeEventListener方法移除事件处理程序,但是并没有起作用。在使用addEventListener和removeEventListener的时候,第二个事件处理程序函数必须是同一个函数才会有作用,我们对上面的代码作一个修改,就可以了。

1 var a=document.getElementById("aa");
2             var callback=function(e){
3                 console.log(this.id);
4             }
5             a.addEventListener("click",callback,false);
6             a.removeEventListener("click",callback,false);

  上面的代码中,我们在addEventListener和removeEventListener中调用的是同一个方法,所以元素aa已经没有点击事件。

  对于IE8以及IE8以下浏览器来说,它们并没有上述的两个方法,但是提供了attachEvent和detachEvent两个方法。这两个只需要传递两个参数:第一参数事件程序名称,第二个事件处理程序函数。

1 var a=document.getElementById("aa");
2             var callback=function(e){
3                 console.log(e.target.innerHTML);
4             }
5             //a.addEventListener("click",callback,false);
6             //a.removeEventListener("click",callback,false);
7             a.attachEvent("onclick",callback);

  上面的代码通过attachEvent添加了事件处理程序,但是attachEvent与addEventListener不一样。在attachEvent的事件处理程序函数中this是指向window的,我们无法获取元素对象。

1 var a=document.getElementById("aa");
2             var callback=function(e){
3                 console.log(this.id);
4             }
5             //a.addEventListener("click",callback,false);
6             //a.removeEventListener("click",callback,false);
7             a.attachEvent("onclick",function(e){
8                 callback.call(a,e);
9             });

  上面的代码,我们通过call修改了this的指向,但是这样会带来另外一个问题,怎么detachEvent?

  • 跨浏览器事件处理程序 

  为了以跨浏览器的事件处理程序,开发人员可以封装适合自己的js库。

 1 var EventUtil={
 2                 addEvent:function(element,type,fn){
 3                     if(element.addEventListener){
 4                         element.addEventListener(type,fn,false);
 5                     }
 6                     else if(element.attachEvent){
 7                         element.attachEvent("on"+type,fn);
 8                     }
 9                     else{
10                         element["on"+type]=fn;
11                     }
12                 },
13                 removeEvent:function(element,type,fn){
14                     if(element.removeEventListener){
15                         element.removeEventListener(type,fn,false);
16                     }
17                     else if(element.detachEvent){
18                         element.detachEvent("on"+type,fn);
19                     }
20                     else{
21                         element["on"+type]=null;
22                     }
23                 }
24             };
25             var aa=document.getElementById("aa");
26             var func=function(e){
27                 console.log(e.type);
28                 EventUtil.removeEvent(aa,"click",func);
29             }
30             EventUtil.addEvent(aa,"click",func);

  上面的EventUtil封装了一个跨浏览器的对象,包含两个方法addEvent和removeEvent。在第25行获取元素对象引用,26行定义了fn函数,30行调用addEvent添加了事件处理程序。这个事件处理程序只能执行一次,因为我们在func函数中又调用了removeEvent函数。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏技术博客

Knockout.Js官网学习(创建自定义绑定)

你可以创建自己的自定义绑定 – 没有必要非要使用内嵌的绑定(像click,value等)。你可以你封装复杂的逻辑或行为,自定义很容易使用和重用的绑定。例如,你可...

1104
来自专栏Jacklin攻城狮

[UIVIew]谈谈对drawRect的理解

2452
来自专栏mukekeheart的iOS之旅

自定义组合控件的过程

自定义组合控件的过程 1.自定义一个View 一般来说,继承相对布局,或者线性布局 ViewGroup; 2.实现父类的构造方法。一般来说,需要在构造方法里初始...

2678
来自专栏九彩拼盘的叨叨叨

学习前端 第6周 第1天

721
来自专栏水击三千

浅谈JavaScript的事件(事件对象)

  在触发DOM上的某个事件时,会产生一个事件对象event,这个对象中包含这所有与事件有关的信息。包括导致事件的元素、事件的类型和事件的相关信息。例如鼠标操作...

2556
来自专栏互联网开发者交流社区

最新jquery+easyui_api培训文档

1434
来自专栏Google Dart

AngularDart Material Design 选择 顶

可以手动(在模板中)或通过SelectionOptions实例指定选项。 可以通过模板或通过检查选择模型将选项标记为已选择。

1122
来自专栏老马寒门IT

01-老马jQuery教程-jQuery入口函数及选择器

这套jQuery教程是老马专门为寒门子弟而录制,希望大家看到后能转发给更多的寒门子弟。视频都是免费,请参考课程地址:https://chuanke.baidu....

2300
来自专栏柠檬先生

VUE 入门基础(8)

十,组件  使用组件   注册     可以通过以下这种方式创建一个Vue实例       new Vue({          el: ...

2229
来自专栏阮一峰的网络日志

如何做到 jQuery-free?

jQuery是现在最流行的JavaScript工具库。 据统计,目前全世界57.3%的网站使用它。也就是说,10个网站里面,有6个使用jQuery。如果只考察使...

3204

扫码关注云+社区

领取腾讯云代金券