轻松掌握:JavaScript观察者模式
2016-08-26 00:48
531 查看
观察者模式
观察者模式也叫“订阅者/发布者”模式,定义对象间的一种一对多的依赖关系,发布者可以向所有订阅者发布消息。观察者模式被广泛地应用于JavaScript客户端编程中。所有的浏览器事件(mouseover,keypress等)都是使用观察者模式的例子。
使用这个模式的最主要目的就是促进对象之间的解耦(弱化对象之间的联系)。在观察者模式中,一组对象订阅另一个对象的指定活动并得到通知。
如:
document.body.addEventListener('click',function(){ alert(2); },false);
以上代码订阅了document.body的click事件,当body被点击时,body便会向订阅者发布消息;
实现观察者模式的一般步骤:
先指定谁充当发布者;
给发布者添加一个缓存列表,用于存放回调函数以便通知订阅者;
发布消息时,发布者会遍历这个缓存列表,依次触发里面存放的订阅者回调函数;还可在回调函数内加入一些参数;
(也可先发布消息,将消息保存起来,当有订阅者时就将该消息重新发布给他)
发布-订阅模式的通用实现:
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设计模式与开发实践》
相关文章推荐
- JavaScript进阶之DOM
- 再谈Json解析
- 【JS点击事件的几种写法】
- JavaScript强化教程——JavaScript 总结
- 对js中事件监听的理解
- Jackson 输出Json时过滤空值、null、“”
- JS打开新窗口的2种方式
- javascript 函数初探 (一)--- 神马是函数
- js删除json数组中指定数组
- 正则表达式及js校验表单代码(注册页面)
- JSON格式转换,String,Array,List,Map
- 数据存储的常用函数
- JavaScript几种函数声明方式的区别
- js生成二级城市联动菜单,动态生成年、月、日字段,生产一个验证码
- JSON 解析 相关文章学习
- JSON 数据解析相关问题
- flexible.js框架改写
- 前端开发:面向对象与javascript中的面向对象实现(一)
- 使用js进行二叉树结构数据与数组结构数据的互相转化
- Newtonsoft.Json(Json.Net)学习笔记-高级使用(转)