代码改变世界

事件模块---自定义事件和自动触发事件

2014-03-27 18:00  明朝  阅读(534)  评论(0编辑  收藏  举报

原理请看:http://www.cnblogs.com/snandy/archive/2011/04/08/2007976.html

直接上自己一步步根据抄袭来的代码的js,自己亲手写了一遍:

var Event = function (){
    

     function _isEmptyObj(obj){ //检查是否为空对象
        for(var a in obj){
            return false;
        }
        return true;
    }
    function _each(ary, callback){
        //遍历一个数据 每次执行的结果的返回值为假时 进行下次遍历
        for(var i=0,len=ary.length; i<len;){
            //调用callBck 返回true的话 从头开始遍历,否则继续遍历
            callback(i, ary[i]) ? i=0 : i++;
        }
    };
    //解除绑定事件
     function _remove(el, type){
         //获取已经绑定的事件集合
        var handler = el.listeners[type]['_handler_'];
        console.log(el.listeners[type]);
        el.removeEventListener ?
            el.removeEventListener(type, handler, false) :
            el.detachEvent('on'+type, handler);
        //删除事件绑定事件函数
        delete el.listeners[type];
        //如果为空,那么删除元素上绑定的属性
        if(_isEmptyObj(el.listeners)){
            delete el.listeners;
        }
    }

    //移除某一类型的事件
    function removeEvent(ele,type,fn){
            //如果ele没有添加的属性,则事件绑定不存在
             if(!ele.listeners) return;
             //获取一类事件的函数
              var listeners = ele.listeners && ele.listeners[type];

              if(listeners){
                      //遍历listeners
                      _each(listeners, function(i, f){
                          //如果 遍历到的函数与要移除的函数的函数名相同时,截取这个函数
                        if(f==fn){
                            return listeners.splice(i, 1);
                        }
                    });
                      //当绑定事件全被干掉了,就解除绑定的["__handle__"]
                    if(listeners.length == 0){
                         _remove(ele,type);
                    }
              }
    }
    //添加自定义事件
    function addEvent(ele,type,fn){

        //给元素加上一个属性,如果存在就等于存在的对象,不存在则为空对象
        ele.listeners = ele.listeners || {};
        //存储独享的key值为type,存在的话直接就为已有的数组,否则为空数组
        var listeners = ele.listeners[type] = (ele.listeners[type] || []);
        //把这一类事件的回调函数存储起来
        listeners.push(fn);
        //每一个函数的listeners,目的是创造一个函数,使addEventListener和attachEvent的内部this都指向元素本身
        if(!listeners["__handle__"]){
            listeners["__handle__"] = function (ev){
                var ev = ev || window.event; //兼容事件对象
                
                for(var i=0,fn;fn=listeners[i++];){
                    //调用一类事件所存储的回调函数,handle被调用时,依次调用;
                    fn.call(ele,ev);
                };    
            };

            ele.addEventListener ? ele.addEventListener(type,listeners["__handle__"],false) :
                                   ele.attachEvent("on"+type,listeners["__handle__"]);
        };
    };
    //自动触发事件
    function dispatch(ele,type){
        try{
            if(ele.dispatchEvent){  //标准浏览器

                var evt = document.createEvent("Event");
                    evt.initEvent(type,true,true);
                    ele.dispatchEvent(evt);
            }else{
                ele.fireEvent("on"+type);
            }
        }catch(e){};
            
    }

    return {
        addEvent:addEvent,
        dispatch:dispatch,
        removeEvent:removeEvent
    }




}();

 

这也是一道面试题!