一个通用的事件处理程序

701 阅读4分钟

什么是事件处理程序?

事件就是用户或浏览器自身执行的某种动作。如click、mousemove、load,都是事件的名字。而响应某个事件的函数就叫做事件处理程序(或事件侦听器)。事件处理程序的名字都是以'on'开头,因此click事件的事件处理程序就是onclick,load事件的事件处理程序就是onload。为事件指定处理程序的方式有多种。

HTML事件处理程序

某个元素支持的每种事件,都可以使用一个与相应的事件处理程序同名的HTML特性来指定。这个特性的值应该是能够执行的JavaScript代码。

// 这里只做简单的简介,如果需要深入的了解关于动态创建的函数,扩展作用域的方式。自行查资料(红宝书三版 p349)

<input type='button' value='onclick me' onclick='alertMessage()'>

<script type='text/javascript'>
    function alertMessage() {
        alert('click me')
    }
</script>

在html中指定事件处理程序的缺点

1、时差问题,因为用户可能会在html元素一出现在页面上就触发相应的事件,但是当时的时间处理程序可能不具备执行条件。以上面的例子来说,假设alertMessage()函数是在按钮下方、页面最底部定义的。如果用户在页面解析alertMessage()之前点击了按钮,就会引发错误。为此,在定义这个处理程序的时候可以增加一个try - catch判断。

<input type='button' value='onclick me' onclick='try{alertMessage()}catch(e) {} '>

<script type='text/javascript'>
    function alertMessage() {
        alert('click me')
    }
</script>
<!--这里就只介绍一种,如果有兴趣知道更多,可以查一下资料-->

DOM0级事件处理程序

将一个函数赋值给一个事件处理程序属性。目前所有现代浏览器都支持,原因一简单,二是具有跨浏览器的优势

// 在下面这些代码运行之前,不会指定对应的事件处理程序,可能点击按钮没有触发alert()方法
let btn = documnet.getElementById('btn');

btn.onclick = function() {
    alert('click me')

    //this此时执行这个元素的引用
}

// 也可以删除指定的方法
btn.onclick = null

DOM2级事件处理程序

addEventListener()和removeEventListener()。所有的dom节点中都包含这两个方法,它们接收三个参数:要处理的事件名称、事件处理函数和一个布尔值。这个布尔值代表true - 捕获阶段调用事件处理程序;false - 冒泡阶段调用

let btn = documnet.getElementById('btn');

// 为什么不采用匿名函数写法,移除方法需要传入的参数和添加的时候相等
function handler(){
    // 与DOM0级事件处理程序一样,这里添加的事件处理程序也是在其依附的元素的作用域
    alert('click', this.id)
}

btn.addEventListener('click', handler, false);

// 参数需要相等
btn.removeEventListener('click', handler, false);

采用DOM2级事件处理程序有什么好处

采用DOM2级处理程序可以添加多个事件处理程序。并且是按照顺序触发,从上往下

let btn = documnet.getElementById('btn');

function handler1(){
    alert('click1', this.id)
}
function handler2(){
    alert('click2', this.id)
}

btn.addEventListener('click', handler1, false);
btn.addEventListener('click', handler2, false);

IE事件处理程序

attachEvent()和detachEvent();接收相同的两个参数:事件处理名称,事件处理函数;由于IE9之前只支持事件冒泡,所以通过attachEvent()添加的事件处理程序都会被添加到冒泡阶段

let btn = documnet.getElementById('btn');

function handler(){
    alert('click', this.id)
}
// !!!注意这里是onclick不是click
btn.attachEvent('onclick', handler)
// 移除方法
btn.detachEvent('onclick', handler)

// attachEvent()与使用DOM0级方法的主要区别在于事件处理程序的作用域。IE中指向window
btn.attachEvent('onclick', function() {alert(this == window)}) // true

采用IE级事件处理程序有与DOM2级事件处理程序有什么区别

采用IE处理程序添加的多个事件处理程序。并且是以相反的方向触发触发,从下往上

let btn = documnet.getElementById('btn');

function handler1(){
    alert('click1', this.id)
}
function handler2(){
    alert('click2', this.id)
}

btn.attachEvent('onclick', handler1);
btn.attachEvent('onclick', handler2);

// click2 ---> click1

一个通用的跨浏览器的事件处理程序

仅供参考

const EventUtils = {
    // 视能力分别使用 dom0 || dom2 || IE 方式,来绑定事件
    // 添加事件
    addEvent: 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;
        }
    },

    // 移除事件
    removeEvent: 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;
        }
    }

    // 获取事件目标
    getTarget: function(event) {
        return event.target || event.srcElement;
    },

    // 获取 event 对象的引用,取到事件的所有信息,确保随时能使用 event
    getEvent: function(event) {
        return event || window.event;
    },

    // 阻止事件(主要是事件冒泡,因为 IE 不支持事件捕获)
    stopPropagation: function(event) {
        if (event.stopPropagation) {
            event.stopPropagation();
        }else {
            event.cancelBubble = true;
        }
    }

    // 取消事件的默认行为
    preventDefault: function(event) {
        if (event.preventDefault) {
            event.preventDefault();
        } else {
            event.returnValue = false;
        }
    }
}