在JavaScript中,想要给元素添加一个事件,其实我们有以下2种方式。

  • (1)事件处理器
  • (2)事件监听器

一、事件处理器

在前面的学习中,如果想要给元素添加一个事件,我们都是通过操作HTML属性的方式来实现,这种方式其实也叫“事件处理器”,例如:

oBtn.onclick = function(){……};

事件处理器的用法非常简单,代码写出来也很易读。不过这种添加事件的方式是有一定缺陷的。先来看一个例子:

举例:

<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> <script> window.onload = function () { var oBtn = document.getElementById("btn"); oBtn.onclick = function () { alert("第1次"); }; oBtn.onclick = function () { alert("第2次"); }; oBtn.onclick = function () { alert("第3次"); }; } </script> </head> <body> <input id="btn" type="button" value="按钮"/> </body> </html>

默认情况下,预览效果如图所示。

当我们点击按钮后,预览效果如图所示。

分析:

在这个例子中,我们一开始的目的是想给按钮添加3次onclick事件,但JavaScript最终只会执行最后一次onclick。从上面也可以看出来了,事件处理器是没办法为一个元素添加多个相同事件的。

你可能会在心里问:“那又如何?”没错,对于同一个元素来说,确实很少需要添加多个相同事件的。可是,有些情况下确实需要这么做才行。比如在点击【提交表单】按钮时,需要验证由用户输入的全部数据,然后再通过AJAX将其提交给服务器。

如果想要为一个元素添加多个相同的事件,该如何实现呢?这就需要用到另外一种添加事件的方式了,那就是——事件监听器。

二、事件监听器

1.绑定事件

所谓的“事件监听器”,指的是使用addEventListener()方法来为一个元素添加事件,我们又称之为“绑定事件”。

语法:

obj.addEventListener(type , fn , false)

说明:

obj是一个DOM对象,指的是使用getElementById()、getElementsByTagName()等方法获取到的元素节点。

type是一个字符串,指的是事件类型。例如单击事件用click,鼠标移入用mouseover等。一定要注意,这个事件类型是不需要加上“on”前缀的。

fn是一个函数名,或者一个匿名函数。

false表示事件冒泡阶段调用。对于事件冒泡,我们在JavaScript进阶教程再详细介绍。这里简单了解即可。

此外,由于IE8浏览器及以下版本已经被Chrome打得快退出历史舞台了,所以对于addEventListener()的兼容性我们不需要考虑IE浏览器。

举例:

<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> <script> window.onload = function () { var oBtn = document.getElementById("btn"); oBtn.addEventListener("click", alertMes, false); function alertMes() { alert("JavaScript"); } } </script> </head> <body> <input id="btn" type="button" value="按钮"/> </body> </html>

浏览器预览效果如图所示。

分析:

//fn是一个函数名 oBtn.addEventListener("click", alertMes, false); function alertMes() { alert("JavaScript"); }
//fn是一个匿名函数 oBtn.addEventListener("click", function () { alert("JavaScript"); }, false);

上面两段代码是等价的:一种是使用函数名;另外一种是使用匿名函数。

举例:

<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> <script> window.onload = function () { var oBtn = document.getElementById("btn"); oBtn.addEventListener("click", function () { alert("第1次"); }, false); oBtn.addEventListener("click", function () { alert("第2次"); }, false); oBtn.addEventListener("click", function () { alert("第3次"); }, false); } </script> </head> <body> <input id="btn" type="button" value="按钮"/> </body> </html>

浏览器预览效果如图所示。

分析:

当我们点击按钮后,浏览器会依次弹出3个对话框。也就是说,我们可以使用事件监听器这种方式来为同一个元素添加多个相同的事件,而这一点是事件处理器做不到的。

此外,一般情况下,如果想要为元素仅仅添加一个事件的话,下面两种方式其实是等价的。

obj.addEventListener("click", function () {……}, false); obj.onclick = function () {……};

举例:多次调用window.onload

<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> <script> //第1次调用window.onload window.onload = function () { var oBtn1 = document.getElementById("btn1"); oBtn1.onclick = function () { alert("第1次"); }; } //第2次调用window.onload window.onload = function () { var oBtn2 = document.getElementById("btn2"); oBtn2.onclick = function () { alert("第2次"); }; } //第3次调用window.onload window.onload = function () { var oBtn3 = document.getElementById("btn3"); oBtn3.onclick = function () { alert("第3次"); }; } </script> </head> <body> <input id="btn1" type="button" value="按钮1" /><br/> <input id="btn2" type="button" value="按钮2" /><br /> <input id="btn3" type="button" value="按钮3" /> </body> </html>

浏览器预览效果如图所示。

分析:

在实际开发中,我们有可能会使用多次window.onload,但是会发现JavaScript只执行最后一次window.onload。为了解决这个问题,我们就可以使用addEventListener()来实现。在这个例子中,我们只需要将每一个window.onload改为以下代码即可:

window.addEventListener("load",function(){……},false);

事实上,还有一种解决方法,那就是使用网上流传甚广的addLoadEvent()函数。addLoadEvent不是JavaScript内置函数,而是需要自己定义的。其中,addLoadEvent()函数代码如下:

//装饰者模式 function addLoadEvent(func) { var oldonload = window.onload; if (typeof window.onload != "function") { window.onload = func; }else { window.onload = function() { oldonload(); func(); } } }

然后我们只需要调用addLoadEvent()函数,就等于调用window.onload了。调用方法如下:

addLoadEvent(function(){ …… });

对于addLoadEvent()函数的定义代码,作为初学者我们暂时不需要去理解。有兴趣的小伙伴可以自行查阅一下。

2.解绑事件

在JavaScript中,我们可以使用removeEventListener()方法为元素解绑(或解除)某个事件。解绑事件与绑定事件是相反的操作。

语法:

obj.removeEventListener(type , fn , false);

说明:

obj是一个DOM对象,指的是使用getElementById()、getElementsByTagName()等方法获取到的元素节点。

type是一个字符串,指的是事件类型。例如,单击事件用click,鼠标移入用mouseover等。一定要注意,这里我们是不需要加上on前缀的。

对于removeEventListener()方法来说,fn必须是一个函数名,而不能是一个函数。

举例: 解除“事件监听器”添加的事件

<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> <script> window.onload = function () { var oP = document.getElementById("content"); var oBtn = document.getElementById("btn"); //为p添加事件 oP.addEventListener("click", changeColor, false); //点击按钮后,为p解除事件 oBtn.addEventListener("click", function () { oP.removeEventListener("click", changeColor, false); }, false); function changeColor() { this.style.color = "hotpink"; } } </script> </head> <body> <p id="content">绿叶学习网</p> <input id="btn" type="button" value="解除" /> </body> </html>

浏览器预览效果如图所示。

分析:

当我们点击【解除】按钮后,再点击p元素,就发现p元素的点击事件无效了。有一点要跟大家说清楚的:如果你想要使用removeEventListener()方法来解除一个事件,那么当初使用addEventListener()添加事件的时候,就一定要用定义函数的形式。

我们观察这个例子会发现,removeEventListener()跟addEventListener()的语法形式是一模一样的,直接抄过去就对了。

addEventListener("click",fn,false); removeEventListener("click",fn,false);

实际上,removeEventListener()只可以解除“事件监听器”添加的事件,它是不可以解除“事件处理器”添加的事件。如果想要解除“事件处理器”添加的事件,我们可以使用“obj.事件名 = null;”来实现,请看下面例子:

举例:解除“事件处理器”添加的事件

<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> <script> window.onload = function () { var oP = document.getElementById("content"); var oBtn = document.getElementById("btn"); //为P元素添加事件 oP.onclick = changeColor; //点击按钮后,为p元素解除事件 oBtn.addEventListener("click", function () { oP.onclick = null; }, false); function changeColor() { this.style.color = "hotpink"; } } </script> </head> <body> <p id="content">绿叶学习网</p> <input id="btn" type="button" value="解除" /> </body> </html>

浏览器预览效果如图所示。

分析:

学了那么多,我们自然而然就会问:解除事件都有什么用呢?一般情况下我们都是添加完事件就算了,没必要去解除事件啊!其实大多数情况确实如此,但是不少情况下是必须要解除事件的。再来看一个例子。

举例:

<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> <script> window.onload = function () { var oBtn = document.getElementById("btn"); oBtn.addEventListener("click", alertMes, false); function alertMes() { alert("那你很棒棒噢~"); oBtn.removeEventListener("click", alertMes, false); } } </script> </head> <body> <input id="btn" type="button" value="弹出" /> </body> </html>

浏览器预览效果如图所示。

分析:

这个例子实现的效果是:限制按钮只可以执行一次点击事件。实现思路很简单,在点击事件函数的最后解除事件就可以了。在实际开发中,像拖拽这种效果,我们在onmouseup事件中就必须要解除onmousemove事件,如果没有解除就会有bug。当然,拖拽效果是比较复杂的,这里不详细展开。对于解除事件,我们学到后面就知道它有什么用了。