初探pub/sub模式

171 阅读1分钟

      +function(w) {
        function Evt() {
          return new Evt.prototype.init();
        }
        Evt.prototype = {
          constructor: this,
          init: function() {
            this.handlers = {}
            return this;
          },
          add: function(type, fn) {
            if(typeof type === 'string' && !(type in this.handlers)) {
              this.handlers[type] = [];    //创建一个事件集
            }
            if(typeof fn === 'function') {
              this.handlers[type].push(fn);    //为当前事件注册函数
            } else {
              throw 'the method of argument not a function'
            }
            return this;
          },
          fire: function(type) {
            var arrevt = [];
            var args = [];
            if(arguments.length > 2) {
              args = Array.prototype.slice.apply(arguments, [1]);    //获取事件参数
            }else if(arguments.length > 1) {
              args = arguments[1];
            }
            if(typeof type === 'string' && (type in this.handlers)) {
              arrevt = this.handlers[type];
            }
            for(var i = 0, len = arrevt.length; i < len; i++) {
              if(args.length > 0) {
                //这里本想让事件触发扔到异步队列中去,然而却访问不到i了,
                //于是这种操作被我弄得无意义了
                +function(i) {
                  setTimeout(function() {
                  arrevt[i](args);
                }, 0);
                }(i);
              }else {
                +function(i) {
                  setTimeout(function() {
                  arrevt[i]();
                }, 0);
                }(i);
              }
              
            }
            return this;
          },
          del: function(type, fn) {
            if(typeof type === 'string' && (type in this.handlers)) {
              if(typeof fn === 'function') {
                var arrevt = this.handlers[type];
                for(var i = 0, len = arrevt.length; i < len; i++) {
                  if(fn === arrevt[i]) {
                    arrevt.splite(i, 1);    //删除该注册函数
                    break;
                  }
                }
              }
            }
            return this;
          }
        }
        Evt.prototype.init.prototype = Evt.prototype;

        window.evt = new Evt;
      }(window);

以上代码将实现一个简单的pub/sub模式,一切皆事件,任何行为都是事件,使用方法

//将所要注册的方法交于一个类统一管理, 这里称为接口inf, 
//这种写法略显"浮肿",但可通过bind创建函数并改变内部this指向
      var inf = {
        test: function(data) {
          console.log(data);
        }
      }
//外部注册事件,并调用事件    传参仅支持数组或者对象
evt.add('test', inf.test).fire('test', 'hello, world');