javascript 事件处理程序

响应某个事件的函数叫做 事件处理程序 (或 事件侦听器 ),例如:click 事件的处理程序就是 onclick

HTML事件处理程序

  1. 某个元素支持的所有事件都可以使用一个与相应事件处理程序同名的HTML特性来指定;
<input type="button" value="click me" onclick="alert('Clicked')" />
  1. 在这个特性里,不能使用未经转义的HTML语法字符:和号(&)、双引号(”“)、小于号(<)或大于号(>);
<input type="button" value="click me" onclick="alert(&quot;Clicked&quot;)" />
  1. 特性值也可以是调用页面中其他地方定义的脚本, HTML事件处理程序在执行时 有权访问全局作用域中的任何代码
<input type="button" value="click me" onclick="showMessage()" />
  1. HTML事件处理程序内部可以 通过 event 变量直接访问事件对象 ,无需自己定义,也不用从函数的参数列表读取;

  2. HTML事件处理程序中的this等于事件的目标元素;

<input type="button" value="click me" onclick="alert(this.value)" />
  1. HTML事件处理程序有着独特的扩展作用域:处理函数内部可以直接访问元素本身、document元素,类似使用with(this)、with(document)进行扩展一样;
<form method="post">
    <input type="text" name="username" value="">
    <input type="button" onclick="alert(username.value)">
</form>
  1. 删除HTML事件处理程序的方法:设置事件处理程序对应的HTML特性值为null;

  2. HTML事件处理程序的三个缺点:


时差问题导致错误:当用户点击你的事件元素时你的处理函数可能还未准备好,例如页面上的处理程序调用了还未加载的脚本程序;


扩展事件处理程序的作用域链在不同浏览器中会有差异;


HTML事件处理程序与HTML紧密耦合,不便于修改。


DOM 0级事件处理程序

var btn = document.getElementById('myBtn');
btn.onclick = function(){
    alert(this.value);
}

###

  1. DOM 0 级事件处理程序将之前HTML事件处理程序的处理权交还给JavaScript,现在为所有浏览器支持;
  2. 每个元素(包括window和document)都有自己的时间处理程序属性;
  3. DOM 0 级方法指定的事件处理程序被认为是元素的方法;
  4. DOM 0 级事件处理程序的作用域是元素本身,处理程序内的this指向元素;
  5. DOM 0 级事件处理程序会在事件流的冒泡阶段被处理;
  6. 缺点:

使用DOM 0 级时间处理程序无法为元素绑定多个事件,后面的同名事件处理程序会覆盖前面的;


定制化不强。

  1. 删除DOM 0 级事件处理程序的方法:
ele.onclick = null;

DOM 2 级事件处理程序

var btn = document.getElementById('myBtn');
var process = function(){
    alert(this.value);
}
btn.addEventListener('click', process, false);

btn.addEventListener('click', process, false);
  1. 两个方法:addEventListener()removeEventListener();
  2. window、document和所有DOM节点都有这两个属性(方法);
  3. 三个参数:事件名、事件处理函数、是否捕获阶段即调用布尔值;
  4. 最佳实践:无特殊要求,第三个参数始终设为false(见11);
  5. 最佳实践:事件处理函数最好预先定义,避免使用匿名函数(见10);
  6. 事件处理程序在其依附的元素的作用域中运行,事件处理函数中的this指向元素本身;
  7. 主要优点:可以为一个元素添加多个同名的事件处理程序;
  8. 通过addEventListener()添加的事件处理程序只能调用removeEventListener()来移除;
  9. removeEventListener()移除事件处理程序时传入的参数必须与添加事件处理程序时传入的参数相同,且第二个参数:事件处理函数的指向必须相同,否则无法移除事件处理程序;
  10. 将第三个参数设置为false是为了最大限度地兼容各个浏览器,除非需要在时间到达目标之前截获它,才将第三个参数设置为true;
  11. IE9+支持(包括9);
  12. 技巧:当事件处理函数是匿名函数时如何移除实践处理程序—使用arguments.callee指向当前函数本身来移除事件处理函数
var clickNumber = 0;

window.addEventListener('click', function(){
    if(clickNumber == 1){
        window.removeEventListener('click', arguments.callee, false);
    }else{
        alert('clicked!');
        clickNumber = 1;
    }
});

IE事件处理程序

var btn = document.getElementById('myDiv');
var process = function(){
    alert(this);
};

btn.attachEvent('onClick', process);

btn.detachEvent('onClick', process);
  1. IE8不支持DOM2级事件;
  2. 注意点:attachEvent()detachEvent()特殊之处

接收的第一个参数为 on+'event',并不是DOM2级事件的'event'


接收无需指定是否捕获阶段截获的布尔值参数,默认冒泡阶段截获事件。


  1. 牢记:attachEvent() 事件处理程序的事件处理函数的作用域是全局作用域,this指向window,与HTML事件处理程序、DOM 0级事件处理程序、DOM 2级事件处理程序有所不同;
  2. attachEvent()也可以为一个元素添加多个同名的时间处理程序;
  3. detachEvent()移除事件处理程序接收的参数必须与attachEvent()接收的参数一致,且事件处理函数的指向必须一致(匿名函数无法被移除)。

跨浏览器的事件处理程序

  1. 基本原则:使用能力检测;

  2. 为保证处理事件的代码能在大多数浏览器下运行,只关注冒泡阶段是很好的选择;

  3. 结合DOM 0 级方法、DOM 2 级方法或IE方法来添加事件,使用能力检测向后兼容;

var EventUtil = {
    addEventHandler: function(element, type, handler){
        if(element.addEventListener){
            element.addEventListener(type, handler, false);
        }else if(element.attachEvent){
            element.attachEvent('on'+type, handler);
        }else{
            element['on'+type]=handler;
        }
    },

    removeEventHandler: function(element, type, handler){
        if(element.removeEventListener){
            element.removeEventListener(type, handler, false);
        }else if(element.detachEvent){
            element.detachEvent('on'+type, handler);
        }else{
            element['on'+type] = null;
        }
    }
}
  1. 以上代码的局限性:没有考虑各个事件处理程序的作用域问题

HTML事件处理程序关联作用域:document、(this.form)、this element


DOM 0 级事件处理程序关联作用域:this element


DOM 2 级事件处理程序关联作用域:this element


IE事件处理程序关联作用域:window