为自定义对象添加自定义事件

由于javascript并没有自己的事件系统,借助于DOM的事件系统,如果只涉及到javascript对象就歇菜了。下面是一个仿制品,不要指望有事件冒泡这东西。


      if(typeof Array.prototype.forEach !== "function"){
        Array.prototype.forEach =  function (fn, scope) {
          for(var i=0,n=this.length>>>0;i<n;i++){
            i in this && fn.call(scope,this[i],i,this)
          }
        }
      }
      var EventDispatcher = {
        $A:function(iterable){
          return Array.prototype.slice.call(iterable)
        },
        createEvents:function(){
          this._listeners = {};
          var names =  this.events || [],name,type;
          names.forEach(function(type){
            name ="on"+ type.replace(/_([a-z])/g, function($1,$2){
              return $2.toUpperCase()
            }).replace(/^\w/, function (s) {
              return s.toUpperCase();
            });

            if(typeof this[name] ==="undefined"){
              this[name] = function(){
                var args = this.$A(arguments);
                return this.attachEvent.apply(this,[type].concat(args))
              }
            }
          },this)
        },
        hasEvent:function(type){
          return (this._listeners[type] instanceof Array && this._listeners[type].length > 0);
        },
        attachEvent:function(){
          var args = this.$A(arguments),
          type = args.shift(), callback = args.shift();
          if (!this.hasEvent(type)) 
            this._listeners[type] = []; 
          var listeners = this._listeners[type]; 
          listeners.push({ callback:callback,args: args });
        },
        detachEvent:function(type,callback){
          if (this.hasEvent(type)) {
            var listeners = this._listeners[type],listener;
            if(typeof callback === "undefined"){
              delete this._listeners[type];
            }else{
              for(var i=0,n=listeners.length;i<n;i++){
                if (listeners[i].callback === callback){
                  listeners.splice(i, 1);
                  return;
                }
              }
            }
          }
        },
        fireEvent:function(){
          var args = this.$A(arguments),type = args.shift();
          if (!this.hasEvent(type)) return ;
          var listeners = this._listeners[type];
          listeners.forEach(function(listener){
            listener.callback.apply(this, listener.args.concat(args))
          },this);
        }
      }

严格来说,这不能算一个类,应该叫接口的东西。当目标类实现它(把EventDispatcher的成员变成目标类的成员),并在原型中提供一个events的字符串数组成员后,我们调用了createEvents,它就拥有事件般的行为,由于没有了DOM的监控,我们需要fireEvent来触发事件。

一个例子:


      var Person = function(name){
        this.name = name
      }
      Person.prototype = {
        events:["layout"]
      }
      var include = function(Concrete,Interface){//使用ruby式的命名方式,用于添加实例成员
        for(var prop in  Interface) {
          Concrete.prototype[prop] = Interface[prop];
        }
      }
      include(Person,EventDispatcher );
      var p = new Person("司徒正美")
      p.createEvents()
      p.onLayout(function(name){
        alert(name)
      });
      p.onLayout(function(name){
        alert(name+"!!")
      });
      p.fireEvent("layout","参数")//依次弹出 "参数" "参数!!"
<!doctype html> <html> <head> <title>javascript 自定义事件 by 司徒正美</title> <meta http-equiv="content-type" content="text/html;charset=UTF-8" /> </head> <body> <div>司徒正美</div> <script type="text/javascript"> if(typeof Array.prototype.forEach !== "function"){ Array.prototype.forEach = function (fn, scope) { for(var i=0,n=this.length>>>0;i<n;i++){ i in this && fn.call(scope,this[i],i,this) } } } var EventDispatcher = { $A:function(iterable){ return Array.prototype.slice.call(iterable) }, createEvents:function(){ this._listeners = {}; var names = this.events || [],name,type; names.forEach(function(type){ name ="on"+ type.replace(/_([a-z])/g, function($1,$2){ return $2.toUpperCase() }).replace(/^\w/, function (s) { return s.toUpperCase(); }); if(typeof this[name] ==="undefined"){ this[name] = function(){ var args = this.$A(arguments); return this.attachEvent.apply(this,[type].concat(args)) } } },this) }, hasEvent:function(type){ return (this._listeners[type] instanceof Array && this._listeners[type].length > 0); }, attachEvent:function(){ var args = this.$A(arguments), type = args.shift(), callback = args.shift(); if (!this.hasEvent(type)) this._listeners[type] = []; var listeners = this._listeners[type]; listeners.push({ callback:callback,args: args }); }, detachEvent:function(type,callback){ if (this.hasEvent(type)) { var listeners = this._listeners[type],listener; if(typeof callback === "undefined"){ delete this._listeners[type]; }else{ for(var i=0,n=listeners.length;i<n;i++){ if (listeners[i].callback === callback){ listeners.splice(i, 1); return; } } } } }, fireEvent:function(){ var args = this.$A(arguments),type = args.shift(); if (!this.hasEvent(type)) return ; var listeners = this._listeners[type]; listeners.forEach(function(listener){ listener.callback.apply(this, listener.args.concat(args)) },this); } } var Person = function(name){ this.name = name } Person.prototype = { events:["layout"] } var include = function(Concrete,Interface){//使用ruby式的命名方式,用于添加实例成员 for(var prop in Interface) { Concrete.prototype[prop] = Interface[prop]; } } include(Person,EventDispatcher); var p = new Person("司徒正美") p.createEvents() p.onLayout(function(name){ alert(name) }); p.onLayout(function(name){ alert(name+"!!") }); p.fireEvent("layout","参数")//依次弹出 "参数" "参数!!" </script> </body> </html>

运行代码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值