最新公告
  • 欢迎您光临码农资源网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!加入我们
  • 学习JavaScript设计模式之观察者模式

    一、定义

    观察者模式(发布-订阅模式):其定义对象间一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。
    在JavaScript中,一般使用事件模型来替代传统的观察者模式。
    好处:

    (1)可广泛应用于异步编程中,是一种替代传递回调函数的方案。 (2)可取代对象之间硬编码的通知机制,一个对象不用再显示地调用另外一个对象的某个接口。两对象轻松解耦。

    二、DOM事件?观察者模式典例

    需要监控用户点击document.body的动作,但是我们没有办法预知用户将在什么时间点击。
    所以,我们订阅document.body上的click事件,当body节点被点击时,body节点便向订阅者发布这个消息!

    document.body.addEventListener("click", function() {
      console.log(1);
    }, false);
    
    // 可以多个订阅者
    document.body.addEventListener("click", function() {
      console.log(2);
    }, false);
    
    doucment.body.click();
    
    

    某网站有header头部、nav导航、消息列表等模块。这几个模块的渲染都需要获取用户登陆信息。
    (1)一般写法:

    $.ajax({
      url: './login',
      type: 'post',
      contentType: 'application/json',
      dataType:'json',
      success: function(data) {
        if(data.status === "success") {
          // 登录成功,渲染header、nav
          header.setInfo(data.headerInfo);
          nav.setInfo(data.navInfo);
        }
      }
    });
    

    (2)使用观察者模式,很轻松解耦!

    $.ajax({
      ...,
      success: function(data) {
        if(data.status === "success") {
          // 登录成功,发布登陆成功消息
          login.trigger("loginsuccess", data);
        }
      }
    });
    
    var header = (function() {
      // 监听消息
      login.listen("loginsuccess", function(data){
        header.setInfo(data.headerInfo);
      });
      return {
        setInfo: function(data) {
          console.log("设置header信息");
        }
      };
    })();
    
    var nav = (function() {
      login.listen("loginsuccess", function(data){
        nav.setInfo(data.navInfo);
      });
      return {
        setInfo: function(data) {
          console.log("设置nav信息");
        }
      }
    })();
    

    三、通用观察者模式

    /*
     * 示例:
     * Event.create("namespace1").listen('click', function(a){
     *   console.log(a);
     * });
     * Event.create("namespace1").trigger("click", 1);
     */
    var Event = (function() {
      var global = this,
        Event,
        _default = 'default';
    
      Event = function() {
        var _listen,
          _trigger,
          _remove,
          _slice = Array.prototype.slice,
          _shift = Array.prototype.shift,
          _unshift = Array.prototype.unshift,
          namespaceCache = [],
          _create,
          find,
          each = function( ary, fn) {
            var ret;
            for(var i = 0, l = ary.length; i < l; i++) {
              var n = ary[i];
              ret = fn.call(n, i, n);
            }
            return ret;
          };
        // 订阅
        _listen = function(key, fn, cache) {
          if(!cache[key]) {
            cache[key] = [];
          }
          cache[key].push(fn);
        };
        // 移除订阅
        _remove = function(key, cache, fn) {
          if(cache[key]) {
            if(fn) {
              for(var i = cache[key].length; i >=0; i++) {
                if(cache[key][i] === fn) {
                  cache[key].splice(i, 1);
                }
              }
            }else {
              cache[key] = [];
            }
          }
        };
        // 发布
        _trigger = function() {
         var cache = _shift.call(arguments),
           key = _shift.call(arguments),
           args = arguments,
           _self = this,
           ret,
           stack = cache[key];
          if(!stack || !stack.length) {
            return;
          }
          return each(stack, function() {
            return this.apply(_self, args);
          });
        };
        // 创建命名空间
        _create = function(namespace) {
          var namespace = namespace || _default;
          var cache = {},
            offlineStack = [], // 离线事件
            ret = {
              listen: function (key, fn, last) {
                _listen(key, fn, cache);
                if (offlineStack == null) {
                  return;
                }
                if (last === 'last') {
                  offlineStack.length && offlineStack.pop()();
                } else {
                  each(offlineStack, function () {
                    this();
                  });
                }
                offlineStack = null;
              },
    
              one: function (key, fn, last) {
                _remove(key, cache);
                this.listen(key, fn, last);
              },
    
              remove: function(key, fn, last) {
                _remove(key, cache, fn);
              },
    
              trigger: function() {
                var fn,
                  args,
                  _self = this;
                _unshift.call(arguments, cache);
                args = arguments;
                fn = function() {
                  return _trigger.apply(_self, args);
                };
                if(offlineStack) {
                  return offlineStack.push(fn);
                }
                return fn;
              }
            };
    
            return namespace ? (namespaceCache[namespace] ? namespaceCache[namespace] : namespaceCache[namespace] = ret) : ret;
          };
    
        return {
          create: _create,
          one: function(key, fn, last) {
            var event = this.create();
            event.one(key, fn, last);
          },
          remove: function(key, fn) {
            var event = this.create();
            event.remove(key, fn);
          },
          listen: function(key, fn, last) {
            var event = this.create();
            event.listen(key, fn, last);
          },
          trigger: function() {
            var event = this.create();
            event.trigger.apply(this, arguments);
          }
        };
      }();
      return Event;
    })();
    

    希望本文所述对大家学习javascript程序设计有所帮助。

    想要了解更多内容,请持续关注码农资源网,一起探索发现编程世界的无限可能!
    本站部分资源来源于网络,仅限用于学习和研究目的,请勿用于其他用途。
    如有侵权请发送邮件至1943759704@qq.com删除

    码农资源网 » 学习JavaScript设计模式之观察者模式
    • 7会员总数(位)
    • 25846资源总数(个)
    • 0本周发布(个)
    • 0 今日发布(个)
    • 293稳定运行(天)

    提供最优质的资源集合

    立即查看 了解详情