浅析JavaScript Event

Event Types

JavaScript的事件类型,一般来说可以分为以下几几大类:

  1. UI Events:例如window.onload, windown.onunload等events;
  2. 鼠标点击事件:例如onmousedown, onmouseup, onmouse, onmouseover, onmousemove, click, dbclick等等;
  3. 键盘点击事件:例如onkeypress, onkeydown, onkeyup
  4. 表单事件:例如onsubmit
  5. 元素聚焦事件:例如onfocus, onblur

Mouse Event

当我们点击鼠标的时候,会触发相对应的鼠标事件,譬如onmousedown, onmouseup, onmousemove, onmouseover, click, dbclick.

event.button可以获取当前用户点击鼠标的位置,1-primary key, 2-secondary key, 3-wheel (IE下面有更多的可能性,1-primary key, 2-secondary key, 3-wheel,4-左右两键同时按下,5-primary + wheel key,6-secondary + wheel key,7-三个按键同时按下)

当我们触发鼠标的双击事件时,实际上发生如下事件: onmousedown > onmouseup > click > onmousedown > onmouseup > click > dbclick (IE下面的情况有点特殊,发生了如下的事件:onmousedown > onmouseup > click > onmousedown > dbclick)

var elem = document.getElementById('elem');

elem.addEventListener('mousedown' function(e) {
    console.debug('mousedown triggered');
}, false);

elem.addEventListener('mouseup' function(e) {
    console.debug('mouseup triggered');
}, false);

Key Event

当我们敲击键盘上的某一个按键的时候,会触发一个key event,例如keydown, keyup, keypress

var elem = document.getElementById('elem');

elem.addEventListener('keydown', function(e) {
    consloe.debug('keydown triggered!');
}, false);

elem.addEventListener('keyup', function(e) {
    consloe.debug('keyup triggered!');
}, false);

elem.addEventListener('keypress', function(e) {
    consloe.debug('keypress triggered!');
}, false);

 

Event Phases

一个事件的触发,从开始到结束,总共经历了Event Capturing > Target Event > Event Bubbling三个过程,为了能够有一个更为直观的理解,请看下面一段简单的HTML代码:

<!DOCTYPE html>
<html>
    <head><title>Event Demo</title></head>
    <body><div id='msg'>Click Me!</div></body>
</html>

 当我们点击Click Me!的时候,触发了click事件,整个事件的流程如下图所示:

 从上图,我们可以很清楚的看到整个click event事件的流程.

Event Object

当我们触发某个事件的时候,我们可以通过event对象来获取当前所发生事件的一些具体的信息,比如event type, event target, event button等等,不同的浏览器,我们获取event object的方式不同:

  • IE浏览器:旧版本的IE浏览器中(IE<9),我们通过window.event来获取当前的event object
  • 其他非IE浏览器:当我们触发某一个时间的时候,会将event object作为一个参数传递给当前所触发或者绑定的事件

Binding Events

通常,我们在HTML页面中,是通过为某一个DOM元素绑定特定Javascript事件来实现页面的交互,由于不同的浏览器有不同的实现,我们一般有如下三种绑定事件的方法:

- 最传统的绑定事件的方法是通过如下的形式来绑定:

var elem = document.getElementById('elem');

elem.onclick = function () {
    console.log('elem is clicked!');  
}

这种方法的优势:

  • 适用性最广发,基本所有的浏览器都支持这种事件的绑定方法

这种方法的劣势:

  • 一个事件只能够绑定一个处理方法
  • 只能够处理Event Bubbling Phase
  • 在绑定的处理方法中,this指向的是window对象,而并不是当前的操作对象
  • 只能通过window.event来获取当前触发的event对象

 

- IE下的事件绑定方法addEvent(type, handler),具体如下所示:

var elem = document.getElementById('elem');

elem.addEvent('onclick', function() {
    console.log('elem is clicked!');
});

这种方法的优势:

  • 对于某一个事件,可以绑定任意多个处理事件
  • 在所绑定的处理事件中,this指向的是当前的操作对象

这种方法的劣势如下:

  • 只适用于IE的事件绑定
  • Event类型必须以'on' + type的形式传递给addEvent方法
  • 只能通过window.event来获取当前的event对象
  • 只能够处理event bubbling phase

- 现代标准浏览器的事件绑定方法:addEventListener(type, handler, capturing)

var elem = document.getElementById('elem');

elem.addEventListener('click', function() {
    console.log('elem is clicked!');
}, false);

这种方法的优势如下:

  • 对于同一个触发事件,可以绑定任意多个处理事件
  • 可以同时处理capturing/bubbling event phase, attachEventList方法的最后一个参数为一个boolean类型的参数,true表示的是处理event capturing phase, false为event bubbling phase
  • 可以轻松获取当前的event object,event object直接以参数的形式传递给绑定的处理方法
  • 在绑定的处理方法中,this指向的是当前的操作对象

这种方法的劣势如下:

  • IE下面的绑定事件不支持此种操作方法

由于不同的浏览器有不同的具体实现,为了实现对event事件的跨浏览器操作,我们有必要开发一个通用的事件绑定方法,次方法应该最大限度的支持现行的所有浏览器,可以轻松获取当前的event object,可以轻松获取当前的操作对象,以下为一个参考的例子:

var $events = {
    guid : 1,

    attachEvent : function (elem, type, handler) {
        if (!handler._guid) {
            handler._guid = this.guid++;
        }

        if (!elem.events) {
            elem.events = {};
        }

        var handlers = elem.events[type];
        if (!handlers) {
            handlers = elem.events[type] = {};

            if (elem['on' + type]){
                handlers[0] = elem['on' + type];
            }
         }

         handlers[handler._guid] = handler;

         elem['on' + type] = handleEvent;

         function handleEvent(e) {
             var rtnValue = true;

             e = e || window.event;

             e = fixEvent(e);

             var handlers = elem.events[type];

             for (var key in handlers) {
                 if (handlers[key](e) === false) {
                     rtnValue = false;
                 }
             }

             return rtnValue;
         };

         function fixEvent(e) {
             e.preventDefautl = fixEvent.preventDefautl;
             e.stopPropagation = fixEvent.stopPropagation;
             return e;
         }

         fixEvent.stopPropagation = function () {
             this.returnValue = false;
         }

         fixEvent.preventDefautl = function () {
             this.cancelBubble = true;
         }
    },

    removeEvent : function (elem, type, handler) {
        if (elem.events && elem.events[type]) {
            delete elem.events[type][handler._guid];
        }
    },
};

Remove Events

我们可以通过以下的方法对事件进行解绑:

  • 通过传统方法绑定的事件,可以充值绑定对象为null来实现事件的解绑,如下所示:
elem.onclick = null
  • 通过IE的addEvent(type, handler)方法绑定的事件,可以通过removeEvent(type, handler)来解绑事件,如下所示:
elem.removeEvent('onclick', handler);
  • 现代标准浏览器,可以通过removeEvent(type, handler)的方式来解绑事件,如下所示:
elem.removeEvent('click', handler);

 

posted @ 2016-01-17 21:48  AndyCBLuo  阅读(193)  评论(0编辑  收藏  举报