*本文已經同步至索引目錄:http://www.cnblogs.com/wbpmrck/archive/2012/05/16/Knockout-introduction.html
KO是什么?
KO不是萬能的,它的出現主要是為了方便的解決下面的問題:
- UI元素較多,用戶交互比較頻繁,需要編寫大量的手工代碼維護UI元素的狀態、樣式等屬性?
- UI元素之間關系比較緊密,比如操作一個元素,需要改變另外一個元素的狀態?
- DOM元素與Js對象之間的數據同步?
- 前端javascript代碼組織不理想?用戶輸入數據校驗、DOM操作、后台交互…,交織在一起?
基礎概念一:viewModel
- 負責處理UI事件的響應,響應用戶操作。
- 負責保存領域模型在前端的變體Model’,比如:Student模型,在UI元素與Model之間同步數據(用戶修改input-->ko修改model,反之亦然)
- 在需要的時候,可以使用Helper方法輕松地從viewModel中剝離出需要傳遞給Server的數據,通過ajax方式與后台交互。
- 負責接收Server端發送過來的數據(可能是Ajax請求),更新模型數據,同時更新UI展現。
基礎概念二:Observable與computed
縱觀KO的所有應用場景,基本上這2個屬性至少會用到一個。個人認為這是KO最常使用的東西。他們用法如下:
- Observable(監控屬性):監控自身屬性的變化,向外部發送通知。外部通過subscribe方法來訂閱屬性的變化事件。
- Computed(依賴屬性):在早期版本中叫做dependentObservable,它通常依賴於其他的Observable,通過計算得出自己的數據。當依賴項改變的時候,computed屬性會接到通知,然后同步更新自身
*這里提2點:
- 雖然本文稱之為“屬性”,但是本質上他們是js的function對象,所以訪問的時候需要加()號
- 默認情況下Computed的同步發生在任意的Observable變化的時候,可是某些情況下我們可能不希望它更新的如此頻繁,比如用戶正在輸入的過程中。KO有其他辦法來延遲更新,在本系列后面會有專門文章介紹。
本章的重點就是講解這2個基本屬性的用法,在后面的“實例講解”中會詳細說明。
如何激活KO綁定
KO中,綁定是需要激活的,可以理解為把viewModel的數據與Html文檔的DOM元素進行分析和關聯。
通常是在頁面元素、viewModel數據加載完畢之后,就可以激活綁定了。當然你可以在任何時候你想進行綁定的時候來激活。
只需要下面的代碼:
var model = new AppViewModel();//實例化一個viewModel ko.applyBindings(model); //綁定到整個頁面
這樣KO會在整個Body中尋找需要進行綁定的元素,與viewModel進行綁定。當然你也可以指定綁定的根節點,這樣的好處:
- 可以縮小KO查找綁定的范圍(畢竟不是整個頁面都需要進行binding)
- 可以同時使用多個viewModel,分別負責不同區域的綁定(是不是你想要的?haha…)
很簡單,加一個參數即可:
var model = new AppViewModel(); ko.applyBindings(model, document.getElementById("Demo1")); //Demo1可能是一個Div
實例講解:Observable
基本語法
1、定義
var myViewModel = { personName: ko.observable('Bob'),//定義叫做personName的監控屬性 personAge: ko.observable(123)//定義叫做personAge的監控屬性 };
2、讀取
var a=myViewModel.personName();//a為'Bob'
3、寫入、連續寫入(鏈式調用)
myViewModel.personName('Mary').personAge(50);//同時修改了2個屬性值
4、訂閱屬性修改事件
myViewModel.personName.subscribe(function(newValue) { alert("The person's new name is " + newValue); }); myViewModel.personName('換個名字');//這時候會彈出alert
Demo
http://jsfiddle.net/wbpmrck/LkTxp/69/embedded/
(如果大家可以看到內嵌Demo,直接點擊Result或者向右小三角看結果)
ps:
- 折騰了半天才繞過了博客園對iframe的過濾,如果個別童鞋看不到demo,請點擊上面的鏈接看demo~
- demo中為了演示功能,提前使用了后面會說到的click綁定,原因是我發現jsFiddle網站上用onclick綁定本地js函數無法訪問。如果有哪位知道的麻煩告知一下,謝謝!
- 大家只需關注點擊處理函數中如何讀取和修改observable的部分即可
實例講解:Computed
在上面例子中,我們有2個屬性firstName和lastName,但是如果我們想顯示一個全名,並且希望這個全名可以根據firstName和lastName的變化而變化,怎么辦?下面Computed登場!
基本語法
1、定義Computed屬性
function AppViewModel() { var self = this; self.firstName = ko.observable('Bob'); self.lastName = ko.observable('Smith'); //下面這個屬性依賴上面的2個屬性存在 self.fullName = ko.computed(function() { return self.firstName() + " " + self.lastName(); }); }
2、讀取Computed屬性
var model = new AppViewModel(); var full =model.fullName();//full="Bob Smith"
Demo
http://jsfiddle.net/wbpmrck/hb8HD/14/embedded/
說明:
為了演示方便,這里提前使用了text綁定和value綁定來顯示viewModel屬性的值,這個綁定很好理解,后面會說到
到這里,大家可能已經感覺到computed比較特殊,他是動態計算的,那么如果要“修改”computed怎么做?看下面。
高級語法
1、可‘寫’的Computed
this.fullName = ko.computed({ //調用fullName()讀取時,會執行這里 read: function () { return this.firstName() + " " + this.lastName(); }, //調用fullName('xx')寫入時,會執行這里 write: function (value) { var lastSpacePos = value.lastIndexOf(" "); if (lastSpacePos > 0) { // Ignore values with no space character this.firstName(value.substring(0, lastSpacePos)); // Update "firstName" this.lastName(value.substring(lastSpacePos + 1)); // Update "lastName" } }, //傳入一個對象,該對象作為this指針在read,write方法中使用 owner: this });
語法說明:
- read屬性:自定義函數,該函數的返回值就是調用fullName()獲取computed屬性值時得到的結果
- write屬性:自定義函數,該函數通過修改依賴項firstName和lastName來修改自身
- owner屬性:傳入對象,該對象作為this關鍵字在read和write方法中使用(函數的調用對象,不明白的童鞋回去看看js基礎...)
Demo
http://jsfiddle.net/wbpmrck/hb8HD/21/embedded/
總結
本文主要介紹了ko中的observable和computed用法,它們是ko的核心組件,也是實現依賴跟蹤的關鍵點。
感謝支持
如果本文對您有幫助的話,請別吝嗇手中的推薦票哦~