轻松掌握:JavaScript观察者模式
观察者模式
观察者模式也叫“订阅者/发布者”模式,定义对象间的一种一对多的依赖关系,发布者可以向所有订阅者发布消息。
观察者模式被广泛地应用于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观察者模式的更多相关文章
- 轻松学习 JavaScript——第 6 部分:JavaScript 箭头函数
JavaScript箭头函数是ECMAScript 6中引入的编写函数表达式的一种简便方法.通常,在JavaScript中,可以通过两种方式创建函数: 函数语句. 函数表达式. 可以如下所示创建函数语 ...
- 轻松学习JavaScript十八:DOM编程学习之DOM简单介绍
一DOM概述 DOM(文档对象模型)是HTML和XML的应用程序接口(API).DOM将把整个页面规划成由节点层级构成的文档. DOM描绘了一个层次化的节点树,执行开发者加入,移除和改动页面的某一部分 ...
- 轻松理解JavaScript闭包
摘要 闭包机制是JavaScript的重点和难点,本文希望能帮助大家轻松的学习闭包 一.什么是闭包? 闭包就是可以访问另一个函数作用域中变量的函数. 下面列举出常见的闭包实现方式,以例子讲解闭包概念 ...
- 轻松理解JavaScript之AJAX
摘要 AJAX技术是网页构建的必备技能之一,本文希望能帮助大家轻松的学习这项技术 一.什么是ajax? ajax(异步javascript xml) 能够刷新局部网页数据而不是重新加载整个网页. 二. ...
- 分针网—每日分享: 怎么轻松学习JavaScript
js给初学者的印象总是那么的"杂而乱",相信很多初学者都在找轻松学习js的途径. 我试着总结自己学习多年js的经验,希望能给后来的学习者探索出一条"轻松学习js之路& ...
- JavaScript观察者模式
观察者模式观察者模式又叫发布订阅模式(Publish/Subscribe),它定义了一种一对多的关系,让多个观察者对象同时监听某一个主题对象,这个主题对象的状态发生变化时就会通知所有的观察者对象,使得 ...
- 怎么轻松学习JavaScript
js给初学者的印象总是那么的“杂而乱”,相信很多初学者都在找轻松学习js的途径.我试着总结自己学习多年js的经验,希望能给后来的学习者探索出一条“轻松学习js之路”.js给人那种感觉的原因多半是因为它 ...
- 理解javascript观察者模式(订阅者与发布者)
什么是观察者模式? 观察者模式又叫做发布订阅模式,它定义了一种一对多的关系,让多个观察者对象同时监听某一个主题对象,这个主题对象的状态发生改变时就会通知所有观察着对象.它是由两类对象组成,主题和观察者 ...
- Javascript观察者模式(Object.defineProperty、Reflect和Proxy实现)
什么是观察者模式? 答:在数据发生改变时,对应的处理函数自动执行.函数自动观察数据对象,一旦对象有变化,函数就会自动执行. 参考<原生JavaScript实现观察者模式>(https:// ...
随机推荐
- SQL Server 自动增长过大
一.背景 我们遇到的问题如下图所示:自动增长无端端就按照这样的比例进行增长: (Figure1:问题所在) 尝试使用SSMS修改自动增长值,就会出现下面的错误: (Figure2:错误信息) 遇到上面 ...
- LINQ系列:LINQ to SQL Where条件
1. 单一条件查询 var expr = context.Products .Where(p => p.ProductName == "LINQ to SQL"); SELE ...
- C#设计模式系列:适配器模式(Adapter)
在实际的软件系统设计和开发中,为了完成某项工作需要购买一个第三方的库来加快开发.这带来一个问题,在应用程序中已经设计好的功能接口,与这个第三方提供的接口不一致.为了使得这些接口不兼容的类可以在一起工作 ...
- ExtJs4之TreePanel
Tree介绍 树形结构,是程序开发,不可缺少的组件之一.ExtJs中的树,功能强大美观实用.功能齐全,拖拉,排序,异步加载等等. 在ExtJs4中Tree和Grid具有相同的父类,因此Grid具有的特 ...
- OpenCASCADE Interpolation - Lagrange
OpenCASCADE Interpolation - Lagrange eryar@163.com Abstract. Power basis polynomial is the most simp ...
- Unity基础知识学习笔记二
1,object Instantiate(object original,Vector3 position,Quaternion rotation) 克隆原始物体,并返回克隆物体. ...
- IOS数据存储之FMDB数据库
前言: 最近几天一直在折腾数据库存储,之前文章(http://www.cnblogs.com/whoislcj/p/5485959.html)介绍了Sqlite 数据库,SQLite是一种小型的轻量级 ...
- 软件工程-构建之法 Visual Studio开发平台的安装与单元测试
一.前言 自从开始了大三下的生活,学校开设一门课程“软件工程”,刚好我们是第一届进行课程改革,不在像以前那样背背概念,考前进行好好突击,然后考试就能过,最后毕业了发现软件工程课程到底我们在其中学习了什 ...
- Spring Boot启动流程详解(一)
环境 本文基于Spring Boot版本1.3.3, 使用了spring-boot-starter-web. 配置完成后,编写了代码如下: @SpringBootApplication public ...
- vue-lazy-render: 延迟渲染大组件,增强页面切换流畅度
最近用element来做项目,在开发的过程中,突然发现页面的操作和切换在数据量大的时候相当卡,后来提了个issue,在furybean解答后才知道,我每个单元格都加了tooltip,会生成大量的节点, ...