自定义事件(转)

上一篇给foo类增加了
addEvent和removeEvent方便事件的注册与注销

这次总结下自定义事件的几种方法

程序代码 程序代码


    <script type="text/javascript">
        <!--

    var foo = function(){ this.init.apply(this,arguments);};

    foo.prototype = {
        init:function(_name){
            this.name = _name;
            this.addEvent('click',document,this.say,this,'hello world!');
        },
        say:function(_ev,_word){
            alert(this.name +':' +_word);
            this.stop();
            this.onSay(_word);
        },
        stop:function(){
            this.removeEvent('click',document,this.say);
        },
        addEvent:function(_event,_element,_fn,_scope,_args){
            var args = Array.prototype.slice.call(arguments, 0);  
            ev = args.shift(),
            element = args.shift(),
            fn = args.shift(),
            scope = args.length>0?args.shift():window;
            element['e'+ev+fn] =  function(_ev){
                _ev == _ev || window.event;
                args.unshift(_ev);
                fn.apply(scope,args);
            };
            if (element.addEventListener) {
                element.addEventListener(ev, element['e'+ev+fn], false);
            } else if (element.attachEvent) {
                element.attachEvent("on" +ev, element['e'+ev+fn]);
            }
        },
        removeEvent:function(_event,_element,_fn){
            if (_element.removeEventListener) {
                _element.removeEventListener(_event, _element['e'+_event+_fn], false);
            } else if (_element.detachEvent) {
                _element.detachEvent("on" +_event, _element['e'+_event+_fn]);
            }
            try {
                delete _element['e'+_event+_fn];
            }catch(_ex){
                _element['e'+_event+_fn] = null;
            }
        },
        onSay:function(){}

    }


var a = new foo('llinzzi');
a.onSay = function(_word){
    alert('事件:'+this.name +'刚说了'+ _word);
}



HTML代码


[Ctrl+A 全部选择 提示:你可先修改部分代码,再按运行]


增加了个onSay的事件,在类定义的时候只定义成空函数,然后在需要的时候调用,定义具体的方法是在类实例化后,给实例中的onSay

缺点是只能定义一次的onSay的回调,如果多次定义后面的会把前面的覆盖掉,修改一下。
程序代码 程序代码


    var foo = function(){ this.init.apply(this,arguments);};

    foo.prototype = {
        init:function(_name){
            this.name = _name;
            this.addEvent('click',document,this.say,this,'hello world!');
        },
        say:function(_ev,_word){
            alert(this.name +':' +_word);
            this.stop();
            this._onSay(_word);
        },
        stop:function(){
            this.removeEvent('click',document,this.say);
        },
        addEvent:function(_event,_element,_fn,_scope,_args){
            var args = Array.prototype.slice.call(arguments, 0);  
            ev = args.shift(),
            element = args.shift(),
            fn = args.shift(),
            scope = args.length>0?args.shift():window;
            element['e'+ev+fn] =  function(_ev){
                _ev == _ev || window.event;
                args.unshift(_ev);
                fn.apply(scope,args);
            };
            if (element.addEventListener) {
                element.addEventListener(ev, element['e'+ev+fn], false);
            } else if (element.attachEvent) {
                element.attachEvent("on" +ev, element['e'+ev+fn]);
            }
        },
        removeEvent:function(_event,_element,_fn){
            if (_element.removeEventListener) {
                _element.removeEventListener(_event, _element['e'+_event+_fn], false);
            } else if (_element.detachEvent) {
                _element.detachEvent("on" +_event, _element['e'+_event+_fn]);
            }
            try {
                delete _element['e'+_event+_fn];
            }catch(_ex){
                _element['e'+_event+_fn] = null;
            }
        },
        _onSay:function(){
            if(!this._onSayArray) return;    
            for(var i=0; i<this._onSayArray.length; i++){
                this._onSayArray[i].apply(this,arguments);
            }
        },
        addOnSay:function(_fn){
            if(!this._onSayArray) this._onSayArray = new Array();
            this._onSayArray.push(_fn);
        }
    }


var a = new foo('llinzzi');
a.addOnSay(function(_word){
    alert('事件1:'+this.name +'刚说了'+ _word);
});
a.addOnSay(function(_word){
    alert('事件2:'+this.name +'刚说了'+ _word);
});



HTML代码


[Ctrl+A 全部选择 提示:你可先修改部分代码,再按运行]


实例通过addOnSay方法来增加事件响应,可以增加多个。

缺点,代码繁琐,如果要增加addOnSayAfter addOnSayBefore 就要增加很多代码。

再修改一下

程序代码 程序代码


    var foo = function(){ this.init.apply(this,arguments);};

    foo.prototype = {
        init:function(_name){
            this.name = _name;
            this.addEvent('click',document,this.say,this,'hello world!');
        },
        say:function(_ev,_word){
            this.fireEvent('saybefore',_word);
            alert(this.name +':' +_word);
            this.stop();
            this.fireEvent('sayafter',_word);
        },
        stop:function(){
            this.removeEvent('click',document,this.say);
        },
        addEvent:function(_event,_element,_fn,_scope,_args){
            var args = Array.prototype.slice.call(arguments, 0);  
            ev = args.shift(),
            element = args.shift(),
            fn = args.shift(),
            scope = args.length>0?args.shift():window;
            element['e'+ev+fn] =  function(_ev){
                _ev == _ev || window.event;
                args.unshift(_ev);
                fn.apply(scope,args);
            };
            if (element.addEventListener) {
                element.addEventListener(ev, element['e'+ev+fn], false);
            } else if (element.attachEvent) {
                element.attachEvent("on" +ev, element['e'+ev+fn]);
            }
        },
        removeEvent:function(_event,_element,_fn){
            if (_element.removeEventListener) {
                _element.removeEventListener(_event, _element['e'+_event+_fn], false);
            } else if (_element.detachEvent) {
                _element.detachEvent("on" +_event, _element['e'+_event+_fn]);
            }
            try {
                delete _element['e'+_event+_fn];
            }catch(_ex){
                _element['e'+_event+_fn] = null;
            }
        },
        fireEvent:function(){
            var args = Array.prototype.slice.call(arguments, 0);  
            var _event = args.shift();
            if(!this.cusEvents) return;
            if(!this.cusEvents[_event]) return;
            for(var i=0; i<this.cusEvents[_event].length; i++){
                this.cusEvents[_event][i].apply(this,args);
            }
        },
        catchEvent:function(_event,_fn){
            if(!this.cusEvents) this.cusEvents = {}
            if(!this.cusEvents[_event]) this.cusEvents[_event] = new Array();
            this.cusEvents[_event].push(_fn);
        }
    }


var a = new foo('llinzzi');

a.catchEvent('saybefore',function(_word){
    alert('事件1:'+this.name +'想说'+ _word);
});

a.catchEvent('sayafter',function(_word){
    alert('事件2:'+this.name +'刚说了'+ _word);
});



HTML代码


[Ctrl+A 全部选择 提示:你可先修改部分代码,再按运行]


最后如果将catchEvent fireEvent addEvent removeEvent 单独放在一个类.EventHeloper
将addEvent和catchEvent整合
EventHeloper.addEvent(element/object,dom event/custom event,callback) 这样还是很方便的。

程序代码 程序代码


    EventHelper = {
        Events:{Dom:{},Custom:{}},
        addEvent:function(_object,_event,_fn,_scope,_args){
            var args = Array.prototype.slice.call(arguments, 0),  
                obj = args.shift(),
                ev = args.shift(),
                fn = args.shift(),
                scope = args.length>0?args.shift():window;
            var eType = obj.nodeType?'Dom':'Custom';
            var fun;
            if(eType=='Dom'){
                sfn = function(_ev){
                    _ev == _ev || window.event;
                    args.unshift(_ev);
                    fn.apply(scope,args);
                }
                if (obj.addEventListener) {
                    obj.addEventListener(ev,sfn, false);
                } else if (obj.attachEvent) {
                    obj.attachEvent("on" +ev,sfn);
                }
            }else {
                sfn = function(){
                    var __sargs = Array.prototype.slice.call(arguments, 0);
                    var _sargs = __sargs.concat(args);
                    fn.apply(scope,_sargs);
                }    
            }
            fun = { fn:fn,sfn:sfn };
            this.Events[eType][obj] = this.Events[eType][obj] || {};
            this.Events[eType][obj][ev] = this.Events[eType][obj][ev] || new Array();
            this.Events[eType][obj][ev].push(fun);
        },
        removeEvent:function(_object,_event,_fn){
            var obj = _object,
                ev = _event,
                fn = _fn;
            var eType = obj.nodeType?'Dom':'Custom';
            if(!this.Events[eType][obj]) return;

            var fun;
            for( var i=0; i<this.Events[eType][obj][ev].length;i++){
                if(fn == this.Events[eType][obj][ev][i].fn){
                    fun = this.Events[eType][obj][ev][i].sfn;
                    this.Events[eType][obj][ev].splice(i,1);
                    break;
                }
            }
            if(eType=='Dom'){
                if (obj.removeEventListener) {
                    obj.removeEventListener(ev, fun, false);
                } else if (obj.detachEvent) {
                    obj.detachEvent("on" + ev, fun);
                }
            }

        },
        fireEvent:function(_object,_event){
            var args = Array.prototype.slice.call(arguments, 0),  
                obj = args.shift(),
                ev = args.shift();
            var eType = 'Custom';
            if((!this.Events[eType][obj]) || (!this.Events[eType][obj][ev])) return;
            for(var i=0; i<this.Events[eType][obj][ev].length; i++){
                this.Events[eType][obj][ev][i].sfn.apply(window,args);
            }
        }
    }




修改一下演示的例子
HTML代码


[Ctrl+A 全部选择 提示:你可先修改部分代码,再按运行]


上面例子的 EventHelper.addEvent方法可以增加自定义事件或者原生的事件
EventHelper.addEvent(document,'click',function(){alert('hello');}); // 原生事件
EventHelper.addEvent(foo,'say',function(){alert('hello');}); // 自定义时间

对应的EventHelper.removeEvent也可以移除自定义事件。

posted on 2009-06-30 10:34  timo.li  阅读(238)  评论(0编辑  收藏  举报

导航