【Knockout】二、監控屬性Observables


MVVM和viewModel

Knockout是建立在以下三大核心功能之上的:

  1. 監控屬性和依賴跟蹤(Observables and dependency tracking)
  2. 聲明式綁定(Declarative bindings)
  3. 模板(Templating)

首先讓我們先來了解下MVVM模式,和viewModel的概念。

MVVM(model、view、viewModel)是一種創建用戶界面的設計模式,他旨在將一個復雜的UI簡單的分割為三個部分:

  • model : 在你的應用用作存儲數據;
  • view : 一個可見的、交互的UI來展現viewModel的狀態;
  • viewModel : 用純凈的代碼來展現ui的數據和操作,可是任意的javascript對象

首先創建一個viewModel,僅僅需要聲明一個任意的javascript對象,例如:

var viewModel = {
  name : 'knockout' };

然后為viewModel創建一個聲明式的綁定view,例如:

<div id="myview" data-bind="text : name"></div>

最后激活knockout,例如

ko.applyBindings(viewModel,document.getElementById('myview'));

data-bind屬性畢竟不是原生的html屬性,即使它能夠完美的工作,但是瀏覽器不認識它,你需要激活knockout使它生效。

這樣就把一個最簡單的viewModel和view綁定到了一起,能夠在view里顯示viewModel的屬性name了,但是,view卻不能再viewModel改變的時候自動更新,viewModel也不能再view改變是自動更新!

Observables

knockout的一個重要功能observable(監控屬性)就是能夠自動自動探測相關的依賴與通知訂閱者(automatic dependency detection and notification triggering),即在建立綁定關系的view和

viewModel之間能夠在一方改變的時候更新另一方的值。

我們將viewModel稍作修改:

 var viewModel = {
   name : ko.observable("knockout") };

現在他就能監控到變化,view就能夠自動更新了。

監控屬性的讀寫操作:

    1.讀取監控屬性的值:

viewModel.name();

    2.寫一個新值到監控屬性中:

viewModel.name("new value");

Observable Arrays

如果你想探測並響應一個對象的變化,使用observables,但是,如果你想探測並響應一系列集合的變化,你應該使用observableArray。

當你需要重復的增加或者刪除時需要顯示或者隱藏一些UI的區域時,observableArray能夠派上大用場。

var myObservableArray = ko.observableArray();    // Initially an empty array
myObservableArray.push('Some value');            // Adds the value and notifies observers

注:observableArray跟蹤的是數組中的對象,而不是對象的狀態。單純的push一個對象到observableArray中,這個對象的屬性並不是observable的,observableArray僅僅跟蹤它所擁有的對象,並當有對象從數組中添加或刪除時通知監聽者。

也可以像這樣初始化一個observableArray:

// This observable array initially contains three objects
var anotherObservableArray = ko.observableArray([
    { name: "Bungle", type: "Bear" },
    { name: "George", type: "Hippo" },
    { name: "Zippy", type: "Unknown" }
]);

Computed Observables (依賴監控屬性)

如果你有一個observable的firstname和一個observable的lastname,你想顯示fullname怎么辦?computed observables派上用場了,它是一個依賴於其他一個或者多個observables的函數,並在任意一個依賴的observable更新時它能夠自動更新。

例如:有這樣一個viewModel:

function AppViewModel() {
    this.firstName = ko.observable('Bob');
    this.lastName = ko.observable('Smith');
}

你可以添加一個computed observable來得到fullname:

function AppViewModel() {
    // ... leave firstName and lastName unchanged ...
 
    this.fullName = ko.computed(function() {
        return this.firstName() + " " + this.lastName();
    }, this);
}

綁定UI元素:

The name is <span data-bind="text: fullName"></span>

當firstname或者lastname改變時fullname能夠自動更新。

可以這樣使用:

  • 監控屬性items表示items的集合;
  • 監控屬性selectedIndexes存儲當前選中的items的index集合;
  • 依賴監控屬性selectedItems表示當前選中的items集合;

改變items或者selectedIndexes都能夠使依賴監控屬性(selectedItems)更新,以達到更新相應的UI元素的目的。

 管理this : 

ko.computed的第二個參數決定了this的值當我們計算依賴監控屬性的值的時候,如果不傳它,將不能夠引用到this.firstname()或者this.lastname().

你也可以這樣做,更加方便:

function AppViewModel() {
    var self = this;
 
    self.firstName = ko.observable('Bob');
    self.lastName = ko.observable('Smith');
    self.fullName = ko.computed(function() {
        return self.firstName() + " " + self.lastName();
    });
}

self能夠在funciton的閉包中被捕獲到,在它任何的內嵌的function中任然是可用的。

判斷一個屬性是否為依賴監控屬性(computed observable)

for (var prop in myObject) {
    if (myObject.hasOwnProperty(prop) && !ko.isComputed(myObject[prop])) {
        result[prop] = myObject[prop];
    }
}

另外,ko提供了一些函數能夠操作監控屬性和依賴監控屬性:

  • ko.isObservable : 對於所有的observable,observable array,computed observable將返回true;
  • ko.isWritableObservable : 對於所有的observable,observable array,writable computed observable返回true;

 使用peek控制依賴關系:

正常情況下,ko的自動依賴跟蹤能夠完成你所期望的工作,但是,你也許希望控制哪個observable來更新或者不更新你的computed observable,peek()函數能夠使你的observable或者computed不創建依賴關系。

例如:

ko.computed(function() {
    var params = {
        page: this.pageIndex(),
        selected: this.selectedItem.peek()
    };
    $.getJSON('/Some/Json/Service', params, this.currentPageData);
}, this);

在這個例子中,一個computed observable依賴其他兩個observable使用ajax獲取數據,當pageIndex改變的時候,computed observable就會更新,重新獲取數據,但是computed observable會忽略掉selectedItem的改變,

因為它使用了peek()。在這種情況下,用戶也許只希望使用selectedItem的值僅僅作為跟蹤目的當一個新的數據集合下載完成以后。

構造computed observable

一個computed observable可以使用以下方式構造:

1.ko.computed( evaluator [, targetObject, options] )

    • evaluator : 一個用來計算當前依賴監控屬性的值的函數。
    • targetObject : 可選,如果定義了,它將作為ko激活你的回調函數時候的this值。
    • options : 可選,備用。

2.ko.computed(options),options包含以下屬性:

    • read : 必須的。用來計算當前依賴監控屬性的值的函數。
    • write : 可選的。使依賴監控屬性writable,這個函數接收一個value參數以用來write到computed observable中。
    • owner : 可選的。如果定義了,它將作為回調函數的this值。
    • pure : 可選的。如果為true,這個computed observable將被設置為pureComputed observable。
    • deferEvaluation : 可選的。不常用
    • disposeWhen : 可選的。不常用
    • disposeWhenNodeIsRemoved : 可選的。不常用。

computed observable的使用

  • dispose() : 手動管理依賴監控屬性,清楚所有依賴的訂閱關系,這個函數非常有用,當你想停止computed observable的更新或者清除內存的時候
  • extend(exteners) : 擴展方法。
  • getDependenciesCount() : 返回當前computed observable的依賴數量。
  • getSubScriptionsCount() : 
  • isActive() : 返回computed observable是否會更新在將來的某個時候,一個沒有任何依賴的computed observable是不會被激活的
  • peek() : 返回computed observable中沒有創建依賴關系的值。
  • subscribe(callback,[callbackTarget,event]) : 注冊一個手動的訂閱來接收computed observable改變的通知。

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM