knockout源碼分析之訂閱

来源:http://www.cnblogs.com/cqhaibin/archive/2016/07/10/5658873.html
-Advertisement-
Play Games

一、主類關係圖 二、類職責 2.1、observable(普通監控對象類) observable(他其是一個function)的內部實現:1.首先聲明一個名為observable的fn(這個可以說是一個類)2.增加一個ko惟一的latestValue(最新值)屬性來存儲形參傳入的值3.如果支持原生_... ...


一、主類關係圖

二、類職責

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相關訂閱(還沒完全理解作用)。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在上一篇《html+ccs3太陽系行星運轉動畫》中實現了太陽系八大行星的基本運轉動畫。 太陽系又何止這些內容,為豐富一下動畫,接下來增加“土星環”和“月球”來充盈太陽系動畫。 下麵是充盈後的動畫效果靜態圖。 一、土星環 修改原來土星的div,在外面放一個包裹層div,class設成saturn-co ...
  • Functionde 對象的實例可以創建構造函數 但是Object對象就不能,當完成一個object對象的實例化後,不能再基於新實例使用new 創建一個實例 添加公有方法 要在構造函數的新實例中添加公有方法,使用點號想它的原型屬性添加即可。 但是不能直接在 Myfunc 上運用 如:Myfunc.n ...
  • ...
  • 含義:滾動條高度 作用:滾動載入(ajax),滾動導航固定定位,滾動彈框定位等等. 展示滾動導航和側邊欄滾動固定定位的效果:查看效果 1、chrome瀏覽器 2、各瀏覽器下 scrollTop的差異 IE6/7/8/9/10: 對於沒有doctype聲明的頁面里可以使用 document.body. ...
  • 關於前端對話框、消息框的優秀插件多不勝數。造輪子是為了更好的使用輪子,並不是說自己造的輪子肯定好。所以,這個博客系統基本上都是自己實現的,包括日誌記錄、響應式佈局等等一些本可以使用插件的。好了,廢話不多時。我們來實現自己的對話框和消息框。 ...
  • jQuery 的 setter/getter 共用一個函數,通過是否傳參來表明它是何種意義。簡單說傳參它是 setter,不傳它是 getter。 一個函數具有多種意義在編程語言中並不罕見,比如函數重載:一組具有相同函數名,不同參數列表的函數,這組函數被稱為重載函數。重載的好處是減少了函數名的數量, ...
  • 文章同步自個人博客:http://www.52cik.com/2016/07/11/generator co.html 此前只是簡單使用而沒有真正的去研究 Generator,這次要好好折騰下這貨。 <! more 非同步編程 對於 jser 來說,非同步非常熟悉了吧,但是真正理解非同步的卻不多,因為大部 ...
  • 一、起因 ES6新納入了很多振奮人心的新特性,真的很讓人忍不住去嘗試一下。不過,由於現在大部分的瀏覽器對ES6的支持程度都不是很好。所以如果想要放心地使用一些新特性,還需要用一些工具,將ES6或者ES7的代碼轉為ES5的代碼。今天,就配置了一下環境,寫了一個react-router,主要是練習自己的 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...