PureMVC(JS版)源码解析(九):View类
在讲解View类之前,我们先回顾一下PureMVC的模块划分:

View.prototype.mediatorMap = null;
我们知道Mediator类有一个onRegister()方法,当Mediator对象在facade中注册时调用的,实际上Mediator对象的注册是通过调用View单例的registerMediator()方法来实现。

View.prototype.registerMediator = function(mediator)
{
if(this.mediatorMap[mediator.getMediatorName()] != null)
{
return;
}
//mediator类继承Notifier类,这是初始化Notifier,给mediator的facade属性赋值
mediator.initializeNotifier(this.multitonKey);
this.mediatorMap[mediator.getMediatorName()] = mediator; //返回mediator感兴趣的消息
var interests = mediator.listNotificationInterests();
// register mediator as an observer for each notification
if(interests.length > 0)
{
//创建一个Observer,把notification和mediator关联起来
var observer = new Observer(mediator.handleNotification, mediator);
for(var i = 0; i < interests.length; i++)
{
this.registerObserver(interests[i], observer);
}
}
//在这里调用了mediator的onRegister()方法
mediator.onRegister();
}
从这段代码中可以明白Mediator类onRegister()方法的调用机制了,这段代码中还有一个地方需要我们去深入研究:
//这段代码什么意思呢?
this.registerObserver(interests[i], observer);
registerObserver(),通过方法名我们可以知道它是用来注册Observer对象的,我们看一下的实现代码:
View.prototype.registerObserver = function(notificationName, observer)
{
if(this.observerMap[notificationName] != null)
{
this.observerMap[notificationName].push(observer);
}
else
{
this.observerMap[notificationName] = [observer];
}
};
View.prototype.removeObserver = function(notificationName, notifyContext)
{
//通过notificationName,可以检索到接受该消息的Observer,返回一个数组
var observers = this.observerMap[notificationName];
for(var i = 0; i < observers.length; i++)
{
if(observers[i].compareNotifyContext(notifyContext) == true)
{
//移除observer
observers.splice(i, 1);
break;
}
}
if(observers.length == 0)
{
delete this.observerMap[notificationName];
}
};
另外,我们知道Mediator类还有一个与onRegister()(注册)方法对应的onRemove()(注销)方法,是Mediator对象在facade中注销时调用的,Mediator对象的注销是通过调用View单例的removeMediator()方法来实现:
View.prototype.removeMediator = function(mediatorName)
{
var mediator = this.mediatorMap[mediatorName];
if(mediator)
{
// for every notification the mediator is interested in...
var interests = mediator.listNotificationInterests();
for(var i = 0; i < interests.length; i++)
{
// remove the observer linking the mediator to the notification
this.removeObserver(interests[i], mediator);
} // remove the mediator from the map
delete this.mediatorMap[mediatorName]; //触发mediator对象的onRemove方法
mediator.onRemove();
} return mediator;
};
mediator对象除了在facade中注册(registerMediator),从facade中注销(removeMediator),还有一个很重要的方法,就是从facade里面检索mediator( retrieveMediator):
View.prototype.retrieveMediator = function(mediatorName)
{
return this.mediatorMap[mediatorName];
};
通过上面的例子,我们可以知道Mediator类onRegister(),onRemove()方法的使用原理(与View类的registerMediator(),removeMediator,retrieveMediator()对应)和怎么注册观察者(registerObserver())、怎么移除观察者(removeMediator())。View类还有一个重要的方法就是给所有的观察者发送消息(notifyObservers()),触发观察者的消息处理函数。
View.prototype.notifyObservers = function(notification)
{
// SIC
if(this.observerMap[notification.getName()] != null)
{
var observers_ref = this.observerMap[notification.getName()], observers = [], observer for(var i = 0; i < observers_ref.length; i++)
{
observer = observers_ref[i];
observers.push(observer);
} for(var i = 0; i < observers.length; i++)
{
observer = observers[i];
//出发了观察者的消息处理函数
observer.notifyObserver(notification);
}
}
};
到目前为止,我们应该可以大致弄清楚mediator对象的消息处理机制了。
我们在Mediator/Command/Proxy通过调用继承自Notifier类的sendNotification()发送消息,实际上是调用View单例的notifyObservers()方法。
View类是个多例类,它用instanceMap来存放View类的实例,我们来看一下它的构造函数:
function View(key)
{
if(View.instanceMap[key] != null)
{
throw new Error(View.MULTITON_MSG);
}; this.multitonKey = key;
View.instanceMap[this.multitonKey] = this;
this.mediatorMap = [];
this.observerMap = [];
this.initializeView();
}; /**
* @protected
* Initialize the Singleton View instance
*
* Called automatically by the constructor, this is your opportunity to
* initialize the Singleton instance in your subclass without overriding the
* constructor
*
* @return {void}
*/
View.prototype.initializeView = function()
{
return;
};
View.getInstance = function(key)
{
if (null == key)
return null; if(View.instanceMap[key] == null)
{
View.instanceMap[key] = new View(key);
};
//实际上是从instanceMap数组中检索
return View.instanceMap[key];
};
总结一下,View类的结构相对于Mediator、Command、Proxy类要复杂许多,但他是PureMVC消息机制的核心,里面的很多方法我们需要记住,反复揣摩,特别是notifyObservers()。最后,附上View类的思维导图。

PureMVC(JS版)源码解析(九):View类的更多相关文章
- 【原创】backbone1.1.0源码解析之View
作为MVC框架,M(odel) V(iew) C(ontroler)之间的联系是必不可少的,今天要说的就是View(视图) 通常我们在写逻辑代码也好或者是在ui组件也好,都需要跟dom打交道,我们 ...
- Mybatis源码解析3——核心类SqlSessionFactory,看完我悟了
这是昨晚的武汉,晚上九点钟拍的,疫情又一次来袭,曾经熙熙攘攘的夜市也变得冷冷清清,但比前几周要好很多了.希望大家都能保护好自己,保护好身边的人,生活不可能像你想象的那么好,但也不会像你想象的那么糟. ...
- AOP源码解析:AspectJAwareAdvisorAutoProxyCreator类的介绍
AspectJAwareAdvisorAutoProxyCreator 的类图 上图中一些 类/接口 的介绍: AspectJAwareAdvisorAutoProxyCreator : 公开了Asp ...
- 【Android源码解析】View.post()到底干了啥
emmm,大伙都知道,子线程是不能进行 UI 操作的,或者很多场景下,一些操作需要延迟执行,这些都可以通过 Handler 来解决.但说实话,实在是太懒了,总感觉写 Handler 太麻烦了,一不小心 ...
- java源码解析之Object类
一.Object类概述 Object类是java中类层次的根,是所有类的基类.在编译时会自动导入.Object中的方法如下: 二.方法详解 Object的方法可以分成两类,一类是被关键字fin ...
- Netty源码解析 -- 内存对齐类SizeClasses
在学习Netty内存池之前,我们先了解一下Netty的内存对齐类SizeClasses,它为Netty内存池中的内存块提供大小对齐,索引计算等服务方法. 源码分析基于Netty 4.1.52 Nett ...
- AOP源码解析:AspectJExpressionPointcutAdvisor类
先看看 AspectJExpressionPointcutAdvisor 的类图 再了解一下切点(Pointcut)表达式,它指定触发advice的方法,可以精确到返回参数,参数类型,方法名 1 pa ...
- Bulma 源码解析之 .columns 类
{说明} 这一部分的源码内容被我简化了,另外我还额外添加了一个辅助类 is-grow. .columns // 修饰类 &.is-centered justify-content: cente ...
- java源码解析之String类(二)
上一节主要介绍了String类的一些构造方法,主要分为四类 无参构造器:String(),创建一个空字符串"",区别于null字符串,""已经初始化,null并 ...
- java源码解析之String类(一)
String是我们接触最多的类,无论是学习中还是工作中,基本每天都会和字符串打交道,从字符串本身的各种拼接.切片.变形,再到和其他基本数据类型的转换,几乎无时无刻都在使用它,今天就让我们揭开Strin ...
随机推荐
- ubuntu 10.04 安装qt 5.0.2
转自ubuntu 10.04 安装qt 5.0.2 从qt project网站下载下来最新的qt5.0.2套件,发现是个.run文件,添加x属性,然后直接sudo ./****.run, 提示 /l ...
- Qt 静态函数QMetaObject::connectSlotsByName(QObject * object)按命名规则自动connect,不需要手动connect
看别人代码看到void on_MyWidget_slotTest(); 就郁闷了,没看到他代码里有connect 却能把信号和槽可以连接起来. 今日回顾书本发现该函所的nb之处. QMetaObjec ...
- JavaScript 作用域和变量提升
本文是这篇文章的简单翻译. 如果按照下面的代码按照JavaScript程序的执行方式执行,alert函数会显示什么? var foo = 1; function bar() { if (!foo) { ...
- POJ_3280_Cheapest_Palindrome_(动态规划)
描述 http://poj.org/problem?id=3280 n 种小写字母构成长度为 m 的串,现在要通过增删字母使串回文,给出每种字母增和删的费用,求最小花费. Cheapest Palin ...
- 国内外最全的asp.net开源项目
转自:http://www.cnblogs.com/fengtangquan/archive/2010/10/19/1855472.html 最近一些项目开始用到CMS系统,最开始是研究JAVA的,无 ...
- python urllib2模块携带cookie
今天干活遇到一个事.有一些网站的一些操作非得要求你登陆才能做,比如新浪微博,你要随便看看吧,不行,非得让你登陆了才能看,再比如一些用户操作,像更改自己的资料啦,个人的隐私啦巴拉巴拉的.想抓取这样的ur ...
- Hadoop之Pig安装
Pig可以看做是Hadoop的客户端软件,使用Pig Latin语言可以实现排序.过滤.求和.分组等操作. Pig的安装步骤: 一.去Pig的官方网站下载.http://pig.apache.org/ ...
- window7电脑设置好了,却无法远程?
设置远程连接: 步骤:右键[我的电脑]-->[属性] 点击[远程设置],然后设置如下: 在 cmd 中 通过 [ipconfig]命令查看IP: 以上设置好了,发现仍无法远程?解决办法如下: 电 ...
- 转载:C++之高精度算法
C++之高精度算法 注意:本文转载自http://blog.sina.com.cn/s/blog_4fdb102b010087ng.html,十分感谢原作者:忍者 前言:由于计算机运算是有模运算 ...
- Java--创建线程及常用方法
继承java.lang.Thread类--Thread类代表线程类 它的常用方法如下: static Thread currentThread():返回当前正在运行的线程对象的引用. static ...