你的位置:首页 > Java教程

[Java教程]DOM事件处理程序


定义

  响应某个事件的函数就是事件处理程序或事件侦听器。

 

HTML事件处理程序

  某个元素支持的每种事件,都可以使用一个与相应事件处理程序同名的HTLM特性来指定。这个特性的值应该是能够执行的JavaScript代码。
  [注意1]事件处理程序中的代码在执行时,有权访问全局作用域中的任何代码。

  事件处理程序会创建一个封装着元素属性值的函数。这个函数中有一个局部变量event,也就是事件对象。通过event变量,可以直接访问事件对象,不用自己定义它,也不用从函数的参数列表中获取。

  <input type="button" value="click" onclick = "console.log(event.type)">//click

  在事件处理程序函数内部,this值等于事件的目标元素

  <input type="button" value="click" onclick = "console.log(this.value)">//click

  在事件处理程序函数内部,可以像访问局部变量一样访问document及该元素本身的成员。如此一来,事件处理程序要访问自己的属性就简单多了。

  <input type="button" value="click" onclick = "console.log(value)">//click

  

  [注意2]如果当前元素是一个表单输入元素,则作用域中还会包含访问表单元素(父元素)的入口。这样,可以让事件处理程序无需引用表单元素就能访问其他表单字段。
  以下代码输出"123"是因为表单元素可以直接通过name属性进行访问

<form action="#">  <input type="text" name="username" value="123">  <input type="button" value="btn" onclick = "console.log(username)"></form>

  

  [注意3]将事件处理程序的相应的属性设置为null,也可以删除以这种方式指定的事件处理程序。

<form action="#">  <input type="text" name="username" value="123">  <input type="button" value="btn" name= "btn" onclick = "console.log(username)"></form><script>document.forms[0].btn.onclick = null;</script>

 

  【缺点】  

  【1】时差问题,因为用户可能会有HTML元素一出现在页面上时就触发相应的事件,但当时的事件处理程序有可能尚不具备执行条件,就会报错。

<input type="button" onclick = "alert(val)"><script src="http://www.qq.com/test.js"></script><script>var val=123;</script>

  【2】HTML与Javascript代码紧密耦合,不利于拓展。

 

DOM0级事件处理程序

  通过Javascript指定事件处理程序传统方式就是将一个函数赋值给一个事件处理程序属性。要使用Javscript指定事件处理程序,首先必须取得一个要操作的对象的引用。
  [注意]每个元素(包括window和document)都有自己的事件处理程序属性,这些属性通常全部小写,将这种属性的值设置为一个函数,就可以指定事件处理程序。

<input type="button" value="btn" id= "btn" ><script>var oBtn = document.getElementById('btn');oBtn.onclick = function(){alert('hello world!');}</script>

  使用DOM0级方法指定的事件处理程序被认为是元素的方法。这时候的事件处理程序是在元素的作用域中运行,程序中的this引用当前元素。

<input type="button" value="btn" id= "btn" ><script>var oBtn = document.getElementById('btn');oBtn.onclick = function(){  alert(this.type);//button}</script>

  可以通过将事件处理程序属性设置为null来删除事件处理程序

btn.onclick = null;

 

DOM2级事件处理程序

  DOM2级事件处理程序定义了两个方法用于处理指定和删除事件处理程序的操作:addEventListener()和removeEventListener()。所有DOM节点中都包含这两个方法,并且它们都接受3个参数:要处理的事件名、作为事件处理的函数和一个布尔值。最后这个布尔值参数如果是true,表示在捕获阶段调用事件处理程序;如果是false,表示在冒泡阶段调用事件处理程序。若最后的布尔值不填写,则和false效果一样。
  [注意]IE8-浏览器不支持addEventListener()的方法

//先弹出document,后弹出window<div class="box" id="box"></div><script>document.addEventListener("click",function(){  alert('document');});window.addEventListener("click",function(){  alert('window');});</script>

  使用DOM2级事件处理程序的好处是可以添加多个事件处理程序,并按照他们添加的顺序触发。

document.addEventListener("click",function(){  alert('document');},false);document.addEventListener("click",function(){  alert('hello world');},false);

  通过addEventListener()添加的事件处理程序只能使用removeEventListener()来移除,移除时传入的参数与添加处理程序时使用的参数相同。这意味着,addEventListener()添加的匿名函数将无法移除。

//以下无效document.addEventListener("click",function(){  alert('document');},false);document.removeEventListener('click',function(){  alert('document');},false);

//以下有效var handle = function(){  alert('document');};  document.addEventListener("click",handle,false);document.removeEventListener('click',handle,false);

 

IE事件处理程序

  IE实现了与DOM中类似的两个方法:attachEvent()和detachEvent()。这两个方法接受相同的两个参数:事件处理程序名称与事件处理程序函数。由于IE8-浏览器不支持事件冒泡,所以通过attachEvent()添加的事件处理程序都会被添加到事件冒泡阶段。
  [注意1]attachEvent()方法只冒泡到document,且IE10-浏览器支持
  [注意2]attachEvent()方法的第一个参数是"onclick",而非DOM的addEventListener()方法中的"click"

//点击div,依次弹出div -> document<div class="box" id="box"></div><script>var oBox = document.getElementById('box');oBox.attachEvent("onclick",function(){  alert('div');});document.attachEvent("onclick",function(){  alert('document');});window.attachEvent("onclick",function(){  alert('window');});</script>

  

  [注意3]在IE中使用attachEvent()与使用DOM0级方法的主要区别在于事件处理程序的作用域。在使用DOM0级方法的情况下,事件处理程序会在其所属元素的作用域内运行;在使用attachEvent()方法的情况下,事件处理程序会有全局作用域中运行,因此this等于window

<div class="box" id="box"></div><script>var oBox = document.getElementById('box');oBox.onclick = function(){  console.log(this);//<div>};oBox.addEventListener("click",function(){  console.log(this);//<div>});oBox.attachEvent("onclick",function(){  console.log(this);//window});</script>

  

  [注意4]当一个元素以多种方式添加事件处理程序时,将按照添加顺序依次执行

//依次输出on、add、attach<div class="box" id="box"></div><script>var oBox = document.getElementById('box');oBox.onclick = function(){  console.log('on');};oBox.addEventListener("click",function(){  console.log('add');});oBox.attachEvent("onclick",function(){  console.log('attach');});</script>  

  

  [注意5]使用attachEvent()方法添加的事件处理程序的触发顺序是有区别的。IE9、10浏览器是按正序执行的,而IE8-浏览器则是按倒序执行的。

//IE9、10浏览器依次输出1、2//IE8-浏览器依次输出2、1document.attachEvent("onclick",function(){alert(1);});  document.attachEvent("onclick",function(){  alert(2);});

  使用attachEvent()添加的事件可以通过detachEvent()来移除,条件是必须提供相同的参数。与DOM方法一样,这也意味着添加的匿名函数将不能被移除。不过,只要能够将对相同函数的引用传给detachEvent(),就可以移除相应的事件处理程序。

//无效document.attachEvent("onclick",function(){  alert(1);});  document.detachEvent("onclick",function(){  alert(1);});

/有效var handle = function(){  alert(1);};document.attachEvent("onclick",handle);  document.detachEvent("onclick",handle);

 

跨浏览器的事件处理程序

var EventUtil = {  addHandler: function(element,type,handler){    if(element.addEventListener){      element.addEventListener(type,handler,false);    }else{      element.attachEvent('on'+type,handler);    }  },  removeHandler: function(element,type,handler){    if(element.removeEventListener){      element.removeEventListener(type,handler,false);    }else{      element.detachEvent('on'+type,handler);    }  }};var handler = function(){  alert(1);}EventUtil.addHandler(document,'click',handler);EventUtil.removeHandler(document,'click',handler);