深入浅析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 EasyUI 数字格式化处理示例
May 05 Javascript
js中window.open打开一个新的页面
Aug 10 Javascript
jQuery Easyui 验证两次密码输入是否相等
May 13 Javascript
限制只能输入数字的实现代码
May 16 Javascript
JavaScript初学者必看“new”
Jun 12 Javascript
Vue中的数据监听和数据交互案例解析
Jul 12 Javascript
JavaScript 自定义事件之我见
Sep 25 Javascript
bootstrap时间控件daterangepicker使用方法及各种小bug修复
Oct 25 Javascript
vue 自定义 select内置组件
Apr 10 Javascript
详解Vue、element-ui、axios实现省市区三级联动
May 07 Javascript
vue中根据时间戳判断对应的时间(今天 昨天 前天)
Dec 20 Javascript
JavaScript检测是否开启了控制台(F12调试工具)
Oct 02 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
使用php4加速网络传输
2006/10/09 PHP
常用的php ADODB使用方法集锦
2008/03/25 PHP
zf框架的校验器InArray使用示例
2014/03/13 PHP
PHP序列化/对象注入漏洞分析
2016/04/18 PHP
PHP实现文件下载【实例分享】
2017/04/28 PHP
javascript显示选择目录对话框的代码
2008/11/10 Javascript
javaScript让文本框内的最后一个文字的后面获得焦点实现代码
2013/01/06 Javascript
Jquery选择器中使用变量实现动态选择例子
2014/07/25 Javascript
jquery向上向下取整适合分页查询
2014/09/06 Javascript
javascript设计模式--策略模式之输入验证
2015/11/27 Javascript
Angularjs在初始化未完毕时出现闪烁问题的解决方法分析
2016/08/05 Javascript
微信小程序 loading 详解及实例代码
2016/11/09 Javascript
jQuery实现倒计时重新发送短信验证码功能示例
2017/01/12 Javascript
Vue.js如何优雅的进行form validation
2017/04/07 Javascript
ES6教程之for循环和Map,Set用法分析
2017/04/10 Javascript
nodejs入门教程三:调用内部和外部方法示例
2017/04/24 NodeJs
你可能不知道的JSON.stringify()详解
2017/08/17 Javascript
JavaScript canvas实现围绕旋转动画
2017/11/18 Javascript
JavaScript捕捉事件和阻止冒泡事件实例分析
2018/08/03 Javascript
Vue.js 图标选择组件实践详解
2018/12/03 Javascript
vue keep-alive列表页缓存 详情页返回上一页不刷新,定位到之前位置
2019/11/26 Javascript
微信小程序实现canvas分享朋友圈海报
2020/06/21 Javascript
详解微信小程序轨迹回放实现及遇到的坑
2021/02/02 Javascript
python在windows命令行下输出彩色文字的方法
2015/03/19 Python
Python使用getpass库读取密码的示例
2017/10/10 Python
详谈套接字中SO_REUSEPORT和SO_REUSEADDR的区别
2018/04/28 Python
PYTHON实现SIGN签名的过程解析
2019/10/28 Python
在python3中使用shuffle函数要注意的地方
2020/02/28 Python
如何在Windows中安装多个python解释器
2020/06/16 Python
解决运行django程序出错问题 'str'object has no attribute'_meta'
2020/07/15 Python
如何在Python3中使用telnetlib模块连接网络设备
2020/09/21 Python
Python爬虫+Tkinter制作一个翻译软件的示例
2021/02/20 Python
linux面试题参考答案(4)
2013/01/28 面试题
半年思想汇报
2013/12/30 职场文书
清洁工岗位职责
2015/02/13 职场文书
青年人初次创业的“五不要”
2019/08/23 职场文书