一、語法介紹
先來看一個簡單的例子:
<span data-bind="text:name"></span>
var obj = {name:ko.observable("tom")}
ko.applyBindings(obj);
這樣會自動完成綁定。其中有3個特別的地方:1. data-bind。2.ko.observable 方法。 3.ko.applyBindings 方法。
1.1 data-bind
data-bind 並不是html元素的固有屬性,但它是完全正確的(符合html5規范),雖然在非html5驗證器中會提示這是一個無效的屬性,但這不會有任何問題。ko就是用data-bind來聲明綁定的。
data-bind 依賴於標簽,也就是data-bind必須作為標簽屬性寫在標簽內。所以我們要輸出一個變量,也必須綁定在標簽內才能輸出。
例如:data-bind="text:name",text 是我們要綁定的“屬性”,例如要為 span、div 賦值,就用 text;這個與jquery 的寫法是一樣的,例如我們會用 $("#id").text(str); 如果是一個編輯框呢?就是 value:name 了。
這里有一個小小的建議,很多時候我們會在標簽里自定義屬性,例如userid,建議都用 data- 開頭,例如:data-userid。
1.2 observable
有了視圖,還要數據。如過上面屬性直接寫為: name:"tom",也是可以完成綁定的。不過這樣就只是單向、一次性綁定了。如果要進行雙向綁定,就要用 observable方法了,用了該方法后,該屬性就不是簡單的js對象屬性了,而是ko特有的對象,取值和賦值也都跟普通屬性不一樣了。
1.3 applyBindings
有了視圖和數據,只需要觸發綁定操作就ok了。ko的applyBindings 方法就是觸發綁定的,它有2個參數,第一個參數是數據對象,第二個參數是可選的,用來設置使用 data-bind 的html元素或容器。例如,有時候界面上有很多處綁定,為了讓結構更加清晰和避免沖突,可以用:ko.applyBindings(obj,document.getElementById("list")); 這樣就表示obj對象綁定在id為list內,聲明有 data-bind 的html元素。
了解了ko的綁定方式后,我們來總結一下數據綁定的幾種方式:
一般的數據綁定有三種:One-Time,One-Way,Two-way。
One-Time綁定模式:從viewModel綁定至UI這一層只進行一次綁定,程序不會繼續追蹤數據的在兩者中任何一方的變化,這種綁定方式適用於數據僅僅會加載一次的情況。
One-Way綁定模式:單向綁定,即object-UI的綁定,只有當viewModel中數據發生了變化,UI中的數據也將會隨之發生變化,反之不然。
Two-Way綁定模式:雙向綁定,無論數據在Object或者是UI中發生變化,應用程序將會更新另一方,這是最為靈活的綁定方式,同時代價也是最大的。
數據綁定只是作為元素的自定義屬性寫上標簽內,並不能決定它是何種綁定。
如果值是通過ko.observable定義的說明是雙向綁定,否則為One-Time綁定,在knockout不存在單向綁定。
二、監控屬性的取值/賦值
2.1 取值
上面說到observable屬性不再是普通屬性,它的取值也不再是obj.name這樣的格式了,而是通過 obj.name() 這樣獲得,實際上我們可以將 name 打印出來,它已經變成一個函數了。
2.2 賦值
同理,賦值不能用 obj.name = "xxx",而是用 obj.name("xxx"); 這種取值和賦值的方法設計和jquery的設計是一樣的。而且,這里也可以鏈式調用,例如:obj.name("xxx").age("20");
2.3 例子
接下來就通過一個例子來體會雙向綁定。當編輯框失去焦點時,右邊的自動更新,點擊清空恢復原狀。這個過程沒有用到dom操作。

html:
<p>姓名:<input type="text" data-bind="value:name" /> 您輸入的姓名:<span data-bind="text:name"></span></p>
<p>年齡:<input type="text" data-bind="value:age" /> 您輸入的姓名:<span data-bind="text:age"></span></p>
<p><input type="button" value="清空" onclick="reset()" /></p>
js:
var obj = {
name : ko.observable(""),
age : ko.observable(0)
}
ko.applyBindings(obj);
function reset(){
obj.name("");
obj.age(0);
}
三、compute
計算屬性。熟悉數據庫的朋友應該了解有個字段叫做【計算字段】,顧名思義,這個字段的值是由其它字段計算而來的。ko里的計算屬性也是一樣的,由其它屬性計算而來,具體計算方式由我們控制。例如上面的例子,我們想在輸入姓名和年齡后自動完成:“姓名,年齡” 這樣的格式就可以用計算屬性。如:
<p>總信息:<span data-bind="text:format"></span></p>
這里把數據改為 function 的寫法,因為在js里函數也是對象,這也是一種推薦的寫法。
function Person(){
this.name = ko.observable("");
this.age = ko.observable(0);
this.format = ko.computed(function(){
return this.name() + "," + this.age();
},this);
}
var person = new Person();
ko.applyBindings(person);
function reset(){
person.name("");
person.age(0);
}
這里要注意的是 this 是作為 computed 的參數傳入。因為我們要獲得Person對象的name和age屬性,而傳入的this,經調用構造函數后,就指向了Person對象。如果沒有這樣傳入呢?那么this指向的是window對象。關於this 的用法也可以看這篇文章:我這樣理解js里的this。
另外,計算屬性還支持下面的寫法,支持更復雜的操作,不過一般很少用到。如下:
this.format = ko.computed({
read:function(){return this.name() + "," + this.age;},
write:function(value){console.log(value);},
owner:this
});
四、總結
observable 是ko 的核心之一,是它在對象的屬性和dom之間建立了綁定。
