深入浅析knockout源码分析之订阅


Posted in Javascript onJuly 12, 2016

Knockout.js是什么?

Knockout是一款很优秀的JavaScript库,它可以帮助你仅使用一个清晰整洁的底层数据模型(data model)即可创建一个富文本且具有良好的显示和编辑功能的用户界面。任何时候你的局部UI内容需要自动更新(比如:依赖于用户行为的改变或者外部的数据源发生变化),KO都可以很简单的帮你实现,并且非常易于维护。

一、主类关系图

深入浅析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源码分析之订阅,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
jquery 弹出层实现代码
Oct 30 Javascript
jQuery 快速结束当前正在执行的动画
Nov 20 Javascript
jquery操作cookie插件分享
Jan 14 Javascript
escape函数解决js中ajax传递中文出现乱码问题
Oct 30 Javascript
JQuery PHP图片在线裁剪实例
Jul 27 Javascript
纯js实现倒计时功能
Jan 06 Javascript
微信小程序 动态绑定数据及动态事件处理
Mar 14 Javascript
Bootstrap表格制作代码
Mar 17 Javascript
vue动态路由:路由参数改变,视图不更新问题的解决
Nov 05 Javascript
vue改变循环遍历后的数据实例
Nov 07 Javascript
Nuxt v-bind绑定img src不显示的解决
Dec 05 Javascript
在VUE中使用lodash的debounce和throttle操作
Nov 09 Javascript
Bootstrap组件系列之福利篇几款好用的组件(推荐二)
Jul 12 #Javascript
JavaScript导航脚本判断当前导航
Jul 12 #Javascript
jQuery bt气泡实现悬停显示及移开隐藏功能的方法
Jul 12 #Javascript
Extjs 点击复选框在表格中增加相关信息行
Jul 12 #Javascript
jQuery插件学习教程之SlidesJs轮播+Validation验证
Jul 12 #Javascript
JavaScript中的事件委托及好处
Jul 12 #Javascript
原生js实现class的添加和删除简单代码
Jul 12 #Javascript
You might like
PHP has encountered an Access Violation
2007/01/15 PHP
PHP执行批量mysql语句的解决方法
2013/05/02 PHP
带你了解PHP7 性能翻倍的关键
2015/11/19 PHP
THINKPHP5.1 Config的配置与获取详解
2020/06/08 PHP
使用Rancher在K8S上部署高性能PHP应用程序的教程
2020/07/10 PHP
js apply/call/caller/callee/bind使用方法与区别分析
2009/10/28 Javascript
JavaScript 序列化对象实现代码
2009/12/18 Javascript
ExtJS 下拉多选框lovcombo
2010/05/19 Javascript
JS获取各种浏览器窗口大小的方法
2014/01/14 Javascript
js和css写一个可以自动隐藏的悬浮框
2014/03/05 Javascript
js 通过html()及text()方法获取并设置p标签的显示值
2014/05/14 Javascript
在Javascript中处理数组之toSource()方法的使用
2015/06/09 Javascript
javascript实现简单加载随机色方块
2015/12/25 Javascript
jquery获取select,option所有的value和text的实例
2017/03/06 Javascript
JavaScript 字符串数字左补位,右补位,取固定长度,截位扩展函数代码
2017/03/25 Javascript
前端图片懒加载(lazyload)的实现方法(提高用户体验)
2017/08/21 Javascript
JS+CSS实现网页加载中的动画效果
2017/10/27 Javascript
详解plotly.js 绘图库入门使用教程
2018/02/23 Javascript
vue的keep-alive用法技巧
2019/08/15 Javascript
element表格翻页第2页从1开始编号(后端从0开始分页)
2019/12/10 Javascript
json_decode 索引为数字时自动排序问题解决方法
2020/03/28 Javascript
详解JavaScript类型判断的四种方法
2020/10/21 Javascript
[52:03]DOTA2-DPC中国联赛 正赛 Ehome vs iG BO3 第三场 1月31日
2021/03/11 DOTA
tf.truncated_normal与tf.random_normal的详细用法
2018/03/05 Python
python切片的步进、添加、连接简单操作示例
2019/07/11 Python
关于Tensorflow使用CPU报错的解决方式
2020/02/05 Python
Python创建临时文件和文件夹
2020/08/05 Python
基于Python的身份证验证识别和数据处理详解
2020/11/14 Python
HTML5实现一个能够移动的小坦克示例代码
2013/09/02 HTML / CSS
美国购车网站:TrueCar
2016/10/19 全球购物
五四演讲稿范文
2014/09/03 职场文书
党的群众路线对照检查材料思想汇报
2014/09/25 职场文书
简单租房协议书
2014/10/21 职场文书
亮剑观后感500字
2015/06/05 职场文书
《圆明园的毁灭》教学反思
2016/02/16 职场文书
CSS3新特性详解(五):多列columns column-count和flex布局
2021/04/30 HTML / CSS