专栏首页cnblogsknockout源码分析之订阅

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相关订阅(还没完全理解作用)。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • DOM事件第二弹(UIEvent事件)

    此文章主要总结UIEvent相关的事件,如有不对的地方,欢迎指正。 一、uitls.js(绑定事件公共类) var fixs = { 'focusin'...

    sam dragon
  • Event(事件)的传播与冒泡

    特性说明和原理图: 标准浏览器和Ie9+浏览器都支持事件的冒泡和捕获,而IE8-浏览器只支持冒泡 标准和Ie9+浏览器用stopPropagation()或c...

    sam dragon
  • 【垂直居中高级篇】你不知道的垂直居中方式

          在Css中对元素进行水平居中是很简单的,如果他是一个行内元素,对它的父元素应用text-align:center;如果是一个块级元素,就对自身应用...

    sam dragon
  • 如何在基于Bytom开发过程中集成IPFS

    比原相关资料:https://github.com/Bytom-Community/Bytom_Docs

    比原链Bytom
  • SAP CRM One Order的事件注册机制

    There are huge number of function modules which are called in one order runtime ...

    Jerry Wang
  • 决策树

    输入: 训练集:D= \{(x_1,y_1),(x_2,y_2),...,(x_m,y_m)\} ;属性集:A= \{a_1,a_2,..,a_d\} 。

    花鸣溪
  • python列表基本语法

    1、列表可以存放任何数据类型,元素可以重复,可以嵌套列表。可以对之进行增删改查操作。 2、创建列表: L=【】或L=list()创建一个空列表; 3、查询或者取...

    py3study
  • Android十八章:是时候在你项目用上greenDAO3GreenDao

    GreenDao3.1.0使用案例包含(增删查改,升级数据库),3.+版本比2.+更加便捷生成DaoMaster和DaoSession 本文项目地址

    ppjun
  • 工具 | Python集合使用详解

    我会在这篇文章介绍Python几种类型的集合。 在开始前,先定义集合是什么。一个集合就像篮子,你可以放进和取出东西,可以是同一类的东西,也可以是不同类的。基本上...

    CDA数据分析师
  • iOS开发之TabBar再次点击实现刷新

    需求 之前已经实现了自定义TabBar,如图所示: ? 自定义TabBar.jpeg 现在需要实现一个类似今日头条TabBar的功能 —— 如果继续点击当前Ta...

    YungFan

扫码关注云+社区

领取腾讯云代金券