Observables,這個詞的翻譯來自湯姆大叔,對於部分翻譯不是很准確的,歡迎大家留言,以得到更好的翻譯。
Knockout是建立在以下3個核心功能之上的:
- 1、 屬性監控與依賴跟蹤
- 2、 聲明式綁定
- 3、 模版機制
在本節中,我們將學習3個核心里面的第一個。但在這之前,先讓我們學習一下MVVM設計模式和View Model的概念。
MVVM和View Models
Model-View-View Model (MVVM)是一種創建用戶界面的設計模式。通過它只要將UI界面分成以下3個部分,就可以使復雜的界面變得簡單:
1、Model,用於存儲你應用程序數據,這些數據表示你業務領域的對象和數據操作(例如:銀行可以進行資金轉賬),並且獨立於任何界面。當使用KO的時候,通常是使用Ajax向服務器請求數據來讀寫這個數據模型。
2、View Model,純粹用於描述數據內容和頁面操作的數據模型。例如,如果你想實現一個列表編輯器,你的ViewModel(數據模型)就是項目清單對象和你所暴露出來的添加和刪除列表項的方法。
注意:這不是UI本身,它不具有任何按鈕和顯示樣式的概念。這不是持久化的數據模型—它僅是用戶當前使用的未保存的數據。當使用KO時,你的View Model(數據模型)是純粹的不包含HTML知識的JavaScript對象,保持View Model(數據模型)抽象在使用時可以保持簡單,因此你可以更簡單的操作管理更復雜的行為。
3、View,代表View Model狀態的一個可見、互動的UI界面。它主要用於顯示View Model的數據信息、發送用戶命令(例如,當用戶點擊按鈕)以及在View Model發生變化時保持自動更新。
使用KO時,你的View層主要就是簡單的將HTML文檔聲明式的綁定到View Model,將它們關聯起來。另外,你也可以利用模版從View Model獲取數據動態生成HTML。
使用KO創建一個View Model,僅僅只需要聲明一個JavaScript對象,例如:
- var myViewModel = {
- personName: 'Bob',
- personAge: 123
- };
你可以創建一個簡單的視圖聲明式綁定到這個View Model上,例如,下面的代碼顯示personName的值:
- The name is <span data-bind="text: personName"></span>
激活Knockout
data-bind屬性並不是HTML固有對象,但使用它是完全正確的(這是完全遵守HTML5,盡管有驗證器指出這是一個無法驗證的屬性,但在HTML4當中使用是不會造成任何問題的)。但瀏覽器並不知道它是什么意思,所以你需要激活Knockout來使其生效。
激活Knockout,只需要將下面的代碼加到<script>標簽中就可以了:
- ko.applyBindings(myViewModel);
你可以將這個代碼放到文檔底部,或者放在頂部包含在DOM處理完成諸如JQuery的$函數方法中。
以上操作完成后,你的View(頁面)顯示的內容等同於編寫以下HTML代碼:
- The name is <span>Bob</span>
下面介紹下ko.applyBindings操作時使用的是什么樣的參數:
第一個參數是你想激活KO時用於聲明式綁定的View Model對象;
第二個參數(可選),你可以使用第二個參數來設置要使用data-bind屬性的HTML元素或容器。例如:
- ko.applyBindings(myViewModel, document.getElementById('someElementId'))
它限制了只有ID為someElementId的元素才能激活使用KO功能,當你在一個頁面中聲明了多個View Model來綁定不同的界面區域時,這樣限制是很有好處的。
在上節中,我們知道了如果創建一個ViewModel,並且如何激活Knockout,本節中,將學習監控屬性相關內容。
Observables
上面,你已經看到如何創建一個基本的數據模型以及如何利用綁定來顯示它的屬性。但是KO最重要的一個屬性就是當View Model發生變化時能夠自動的更新UI界面。KO是如何能夠知道你的View Model已經發生改變了呢?答案是:你需要將你的model屬性聲明成observable的, 因為它是非常特殊的JavaScript 對象,能夠通知用戶它的改變以及自動檢測依賴關系。
例如:重寫上述例子中的View Model為以下代碼:
- var myViewModel = {
- personName: ko.observable('Bob'),
- personAge: ko.observable(123)
- };
你根本不需要對View進行更改,所有的data-bind語法依然正常工作。所不同的是,現在它能夠自動檢測變化,並通知它自動更新界面(View)。
Reading and writing observables
並不是所有的瀏覽器都支持JavaScript的getters and setters (比如IE),所以,為了兼容,ko.observable監控的對象都是方法。
1、讀取當前監控的屬性值,只需要直接調用observable(不需要參數),在這個例子當中,調用myViewModel.personName()將會返回'Bob',調用myViewModel.personAge() 將會返回'123'
2、寫一個新值到監控屬性上,調用observable方法,將要寫的值作為一個參數傳入即可。例如,調用myViewModel.personName('Mary') 將會把名稱改變成 'Mary'。
3、一次性改變Model對象監控的多個屬性值,你可以使用鏈式方法。例如:myViewModel.personName('Mary').personAge(50) 將會把名稱改變成'Mary'將年齡設置為 50.
監控屬性最重要的一點就是可以隨時監控,也就是說,其他代碼可以告訴它哪些是需要通知發生變化的。這就是為什么KO會有如此多的內置綁定語法。所以,當你在頁面中編寫data-bind="text: personName",text 會綁定注冊到自身,當personName發生變化時,它能夠立即得到通知。
當你通過調用 myViewModel.personName('Mary') 將名稱的值改變成為'Mary'時,text綁定會自動更新新值到其對應的DOM對象元素上,這就是為什么改變數據模型能夠自動刷新View頁面。
監控屬性的顯示訂閱
通常情況下,你不需要手工訂閱,所以初學者可以跳過這一節。
對於高級用戶,如果你想要注冊自己的訂閱來通知監控屬性的變化,你可以使用subscribe 方法。例如:
- myViewModel.personName.subscribe(function(newValue) {
- alert("The person's new name is " + newValue);
- });
subscribe 方法在KO內部很多地方都有用到。你也可以終止自己的訂閱:首先獲取到這個訂閱,然后調用dispose方法即可。例如:
- var subscription = myViewModel.personName.subscribe(function(newValue) { /* do stuff */ });
- // ...then later...
- subscription.dispose(); // I no longer want notifications
大多數時間,你不需要這么做,因為內置的綁定和模版系統功能在管理訂閱上已經做了很多工作。