• 轻松掌握:JavaScript观察者模式


    观察者模式

    观察者模式也叫“订阅者/发布者”模式,定义对象间的一种一对多的依赖关系,发布者可以向所有订阅者发布消息。

    观察者模式被广泛地应用于JavaScript客户端编程中。所有的浏览器事件(mouseover,keypress等)都是使用观察者模式的例子。

    使用这个模式的最主要目的就是促进对象之间的解耦(弱化对象之间的联系)。在观察者模式中,一组对象订阅另一个对象的指定活动并得到通知。

    如:

    document.body.addEventListener('click',function(){
        alert(2);
    },false);
    

    以上代码订阅了document.body的click事件,当body被点击时,body便会向订阅者发布消息;

    实现观察者模式的一般步骤:

    1. 先指定谁充当发布者;
    2. 给发布者添加一个缓存列表,用于存放回调函数以便通知订阅者;
    3. 发布消息时,发布者会遍历这个缓存列表,依次触发里面存放的订阅者回调函数;还可在回调函数内加入一些参数;
      (也可先发布消息,将消息保存起来,当有订阅者时就将该消息重新发布给他)
    发布-订阅模式的通用实现:
    var Publisher = (function(){
        //listenerList用来保存一系列的key,每个key为保存了所有订阅者函数fn的数组{ keyA:[fn1,fn2...], keyB:[...]...}
        //类似:可以为同一事件注册多个回调函数
        var listenerList = {};
        return {
            addListener: function(key,fn){
                if(!listenerList[key]){
                    listenerList[key] = [];
                }
                if(listenerList[key].indexOf(fn) === -1){ //检测fn是否已订阅,注意indexOf方法不支持IE9以下,可用for循环代替
                    listenerList[key].push(fn);
                }
            },
            publish: function(){
                var key = Array.prototype.shift.call(arguments),
                    fns = listenerList[key];
                if(!fns||fns.length === 0){
                    return false;
                }
                for(var i = 0,fn;fn = fns[i++];){
                    fn.apply(this,arguments);
                }
            },
            removeListener: function(key,fn){
                var fns = listenerList[key];
                if(!fns){
                    return false;
                }
                if(!fn){ //若没指定fn,则表示取消所有订阅
                    fns && (fns.length = 0);
                }else{  //可直接用fns.splice(listenerList[key].indexOf(fn),1);但indexOf方法不支持IE9以下
                    for(var l = fns.length - 1; l >=  0; l--){
                        if(fns[l] === fn){
                            fns.splice(l,1);
                        }
                    }
                }
            }
        };
    })();
    
    Publisher.addListener('month',function(num){  //订阅month
        console.log('本月数量: '+num);
    });
    Publisher.addListener('month',function(price){
        console.log('本月价格: '+price);
    });
    Publisher.addListener('week',function(num){
        console.log('本周数量: '+num);
    });
    Publisher.publish('month',123);  //手动发布消息
    //本月数量: 123
    //本月价格: 123
    Publisher.publish('week',5);
    //本周数量: 5
    

    实际应用:

    $.ajax('http://xxx.com?login',function(data){
       Publisher.publish('loginSuccess',data);  //若登录成功则向所有订阅者发布登录成功的消息
    });
    //以下在各个模块添加订阅消息
    var header = (function () {
        Publisher.addListener('loginSuccess', function (data) {
            header.setAvatar(data.avatar);
        });
        return {
            setAvatar: function (data) {
                console.log('设置header模块的头像')
            }
        }
    })();
    var nav = (function () {
        Publisher.addListener('loginSuccess', function (data) {
            nav.setAvatar(data.avatar);
        });
        return {
            setAvatar: function (avatar) {
                console.log('设置header模块的头像')
            }
        }
    })();
    //...可随意添加其他模块
    

    参考文献:
    《JavaScript模式》
    《JavaScript设计模式与开发实践》

  • 相关阅读:
    解决虚拟机中使用ntpdate报错:ntpdate[46700]: no server suitable for synchronization found
    Hive的三种安装方式(内嵌模式,本地模式远程模式)
    攻城狮在路上(陆)-- 提交运行MapReduce程序到hadoop集群运行
    攻城狮在路上(陆)-- 配置hadoop本地windows运行MapReduce程序环境
    攻城狮在路上(陆)-- hadoop分布式环境搭建(HA模式)
    攻城狮在路上(陆)-- hadoop单机环境搭建(一)
    Linux下Keepalived+LVS-DR模式配置高可用负载均衡集群
    Git版本控制管理学习笔记5-提交
    Git版本控制管理学习笔记4-文件管理和索引
    Git版本控制管理学习笔记3-基本的Git概念
  • 原文地址:https://www.cnblogs.com/susufufu/p/5808885.html
Copyright © 2020-2023  润新知