knockout源码分析之订阅
一、主类关系图

二、类职责
2.1、observable(普通监控对象类)
observable(他其是一个function)的内部实现:
1.首先声明一个名为observable的fn(这个可以说是一个类)
2.增加一个ko惟一的latestValue(最新值)属性来存储形参传入的值
3.如果支持原生__proto__属性就利用hasOwnProperty来判断属性是否存在的方式来继承,判断__proto__代码(在utils类中)
var canSetPrototype = ({ __proto__: [] } instanceof Array);
4.ko.subscribable的fn属性的init方法对observable进行初始化(主要增加订阅、发布相关属性)
5.observable再继承observabelFn相关属性和方法(observabelFn包含观察、值变化前、值变化后的执行策略)
// Define prototype for observables
var observableFn = {
'equalityComparer': valuesArePrimitiveAndEqual,
peek: function() { return this[observableLatestValue]; },
valueHasMutated: function () { this['notifySubscribers'](this[observableLatestValue]); },
valueWillMutate: function () { this['notifySubscribers'](this[observableLatestValue], 'beforeChange'); }
};
6.返回observable方法的实现(如果传入参数就是设置,无参则是获取)
7、此类还提供了hasPrototype(判断指定实例是否拥有此属性)、isObservable(判断指定实例是否为监控对象)、isWriteableObservable(是否为可写的监控对象)。
2.2、observableArray(数组监控对象类)
1.先执行ko.observable方法,让其对象变为一个可监控的类(名为result);
2.然后扩展ko.observableArray中的fn对象(ko.observabelArray的fn重写了数组相关的操作方法,如remove、push等)
3.通过extends扩展一个方法(trackArrayChanages,详细介绍见2.5)
4.返回扩展好的result对象。
ko.observableArray = function (initialValues) {
initialValues = initialValues || [];
if (typeof initialValues != 'object' || !('length' in initialValues))
throw new Error("The argument passed when initializing an observable array must be an array, or null, or undefined.");
var result = ko.observable(initialValues);
ko.utils.setPrototypeOfOrExtend(result, ko.observableArray['fn']);
return result.extend({'trackArrayChanges':true});
};
2.3、subscribable(订阅对象类)
1.实现订阅、发布的功能模块,对observable、observableArray来说是必不可少的基类
2.这里有一个subscrible方法,用于对监控对象变化的订阅接口,开发则可以用此继切入点
subscribe: function (callback, callbackTarget, event) {
var self = this;
event = event || defaultEvent;
var boundCallback = callbackTarget ? callback.bind(callbackTarget) : callback;
var subscription = new ko.subscription(self, boundCallback, function () {
ko.utils.arrayRemoveItem(self._subscriptions[event], subscription);
if (self.afterSubscriptionRemove)
self.afterSubscriptionRemove(event);
});
if (self.beforeSubscriptionAdd)
self.beforeSubscriptionAdd(event);
if (!self._subscriptions[event])
self._subscriptions[event] = [];
self._subscriptions[event].push(subscription);
return subscription;
}
3.extend:此方法用于添加extends方法加入的扩展类(如observableArray.changeTracking扩展类)
4.extend扩展的方法,会在监控对象注册后立即执行,传入参数为target(当前对象)、options(extend调用时传入的参数)
5.extend就是安装扩展的方法,他会立即执行扩展中的代码。
2.4、extends(扩展监控对象类)
1.ko默认的扩展集合
2.提供一个applyExtenders方法来安装扩展
function applyExtenders(requestedExtenders) {
var target = this;
if (requestedExtenders) {
ko.utils.objectForEach(requestedExtenders, function(key, value) {
var extenderHandler = ko.extenders[key];
if (typeof extenderHandler == 'function') {
target = extenderHandler(target, value) || target;
}
});
}
return target;
}
2.5、observableArray.changeTracking(扩展监控对象的一个具体实现)
1.此扩展主要实现对数组变化的监控,然后计算数组的差异,以及触发相关的订阅事件
2.cacheDiffForKnownOperation:缓存对数组的操作,以备差异比较
3.beforeSubscriptionAdd、afterSubscriptionRemove相关订阅(还没完全理解作用)。
knockout源码分析之订阅的更多相关文章
- knockout源码分析之computed(依赖属性)
一.序列图 二.主要代码文件 1.dependentObservable.js:主要包含ko.computed相关方法的处理2.dependencyDetection.js:主要包含依赖的监控上下文对 ...
- knockout源码分析之执行过程
一.执行流程 二.主要类分析 2.1. 在applyBindings中,创建bindingContext,然后执行applyBindingsToNodeAndDescendantsInternal方法 ...
- redis源码分析之发布订阅(pub/sub)
redis算是缓存界的老大哥了,最近做的事情对redis依赖较多,使用了里面的发布订阅功能,事务功能以及SortedSet等数据结构,后面准备好好学习总结一下redis的一些知识点. 原文地址:htt ...
- RxJava2 中多种取消订阅 dispose 的方法梳理( 源码分析 )
Github 相关代码: Github地址 一直感觉 RxJava2 的取消订阅有点混乱, 这样也能取消, 那样也能取消, 没能系统起来的感觉就像掉进了盘丝洞, 迷乱… 下面说说这几种情况 几种取消的 ...
- jQuery 2.0.3 源码分析 Deferred(最细的实现剖析,带图)
Deferred的概念请看第一篇 http://www.cnblogs.com/aaronjs/p/3348569.html ******************构建Deferred对象时候的流程图* ...
- 移动web app开发必备 - Deferred 源码分析
姊妹篇 移动web app开发必备 - 异步队列 Deferred 在分析Deferred之前我觉得还是有必要把老套的设计模式给搬出来,便于理解源码! 观察者模式 观察者模式( 又叫发布者-订阅者模 ...
- 轻量级前端MVVM框架avalon源码分析-总结
距avalon0.7版本发布有一段时间,由于之前的稳定性,就停止一段时间更新,期间研究了下Knockout源码,也尝试写了一个小型的mvvm的实现模型,仅仅只是仿造ko的核心实现,把无关的东西给剥离掉 ...
- rxjava源码分析
RXjava响应式编程 此文作者大暴雨原创,转载请注明出处. 如果线程的知识不是很丰富,请先查看 rxjava源码中的线程知识 一文 rxjava总结就是:异步实现主要是通过扩展观察者模式 ...
- This Node源码分析
看军哥博客有Rtos的源码分析,手痒耍宝把自己读的源码笔记分享出来.愿与众君互相讨论学习 namespace ros { namespace names { void init(const M_str ...
随机推荐
- double保持精度,防止小数点后数字的丢失的小方法
一般情况下,输入带小数点的字面值,编译器会把它解析成double 类型. 例如:一个字面值被直接放到代码中,由于带小数点所以,默认值为double类型 输出结果是:1.12345678912345 ...
- [转载]基于TFS实践敏捷-实现用户场景
您是新用户的 Visual Studio 应用程序生命周期管理 (ALM) 和 Team Foundation Server (TFS) 吗? 您想知道如何您和您的团队可以获得最大受益的这些工具来生成 ...
- 专业IT培训机构-传智播客
http://user.qzone.qq.com/1467400757/blog/1414135584
- maven中使用junit老是找不到包
如题,烦恼好久,突然看到scope一直是test,改成compile就好了. compile (编译范围) compile是默认的范围:如果没有提供一个范围,那该依赖的范围就是编译范围.编译范围依赖在 ...
- html/css基础篇——关于浏览器window、document、html、body高度的探究
首先说明本人所理解的这几个元素的计算 window高度应当是文档所在窗口的可视高度(没有包括浏览器的滚动条),计算方法document.documentElement.clientHeight doc ...
- web框架--flask
flask介绍 Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架,对于Werkzeug本质是Socket服务端,其用于接收http请求并对请求 ...
- iOS Swift编程语言
Swift,苹果于2014年WWDC(苹果开发者大会)发布的新开发语言,可与Objective-C*共同运行于Mac OS和iOS平台,用于搭建基于苹果平台的应用程序. Swift是一款易学易用的编程 ...
- Emit学习(3) - OpCodes - 动态添加属性、构造函数、方法
上一篇介绍了 IL 的部分, 基础的部分, 暂时就介绍到那里了, 接下来要进入代码编写阶段了. 今天的主题是 在代码运行的过程中, 去动态的创建类, 属性, 方法. 来源:http://www.cnb ...
- .net概念之程序集说明
一.程序集的一些基本概念: 程序集是包含一个或多个类型定义文件和资源文件的集合.它允许我们分离可重用类型的逻辑表示和物理表示. 程序集是一个可重用.可实施版本策略和安全策略的单元.它允许我们将类型和资 ...
- lua的string.gsub初使用
今天在学习lua,熟悉项目代码的过程中,发现string.gsub好高级,所以在此mark下. 以下是lua5.1的官方文档介绍. string.gsub (s, pattern, repl [, n ...