2012年8月14日 星期二

knockoutjs 7 綁定特性 補註

knockoutjs 7 綁定特性 補註

範例一 (單獨屬性):
  • 這個範例操作UI可以改變屬性值,而程式修改屬性值也可Refresh UI。
$(window).ready(function(){
//產生一個ViewModel
var  myViewModel={
   name:ko.observable('鄭多燕')  
};

//偵聽name屬性值變動
myViewModel.name.subscribe(function(newValue) {
  $('#sp').val(myViewModel.name());
});

//啟動KO綁定
ko.applyBindings(myViewModel);
});

<input type="text" data-bind="value:name" /></br>   //文字框一
<input id="sp" type="text" disabled="true" /></br>  //文字框二

結果:
    這個例子有兩個文字框,其中第一個文字框可以輸入,第二個不能,當第一個文字框改變後,會執行$('#sp').val(myViewModel.name());,如此會將現在myViewModel的name設定給第二個文字框,而結果會是文字框二的內容將會跟隨文字框一變動,由此測試可知,當UI上的值改變具有KO觀察性質的屬性值也會自改變。


再來是關於物件型態綁定
範例二 (物件型態屬性):
  • 這個範例是沒有使用with的情況,並且未對其Object的屬性下observable。
  • (UI操作無法更新屬性質,而程式直接修改屬性質也無法 Refresh UI)。
$(window).ready(function(){
var  myViewModel={
    userInfo:ko.observable({name:'maggie',age:25})
};
        //啟動KO綁定
ko.applyBindings(myViewModel);

//btn按下後,將name值寫回id=sp的input

$('#btn').click(function(){
$('#sp').val(myViewModel.userInfo().name);

});

 //使用程式直接修改

$('#btn2').click(function(){
myViewModel.userInfo().name = "jeffrey";
});

});

<!--DOM-->
<input type="text" data-bind="value:userInfo().name" /></br>  //文字框一
<input id="sp" type="text" disabled="true" /></br>            //文字框二
<input id="btn" type="button" value="顯示目前name數值"/>        //取值按鈕
<input id="btn2" type="button" value="使用程式修改數值"/>        //設值按鈕


結果:
    這個範例當你將文字框一的內容改變後,然後按下取值按鈕,結果會發現name並沒有被改變,而若按下設值按鈕之後在按下取值會發現,文字框二數值會被改變成jeffrey,但是文字框不會改變,這樣使用一不注意會造成邏輯錯誤。



範例三: 

  • 使用with的範例 
  • (UI操作改變會同時跟改屬性,但程式直接修改屬性卻無法Refresh UI)。
$(window).ready(function(){
var  myViewModel={
    userInfo:ko.observable({name:'maggie',age:25})
};

ko.applyBindings(myViewModel);

$('#btn').click(function(){
$('#sp').val(myViewModel.userInfo().name);
});

$('#btn2').click(function(){
myViewModel.userInfo().name = "jeffrey";
});
});


<div data-bind="with:userInfo">
<input type="text" data-bind="value:name" /></br>       //文字框一
<input id="sp" type="text" disabled="true" /></br> //文字框二 <input id="btn" type="button" value="顯示目前name數值"/>  //取值按鈕 <input id="btn2" type="button" value="使用程式修改數值"/>  //設值按鈕</div>

結果:
   
這個範例在文字框一修改後然後按下取值按鈕,這時候會發現文字框二的內容與文字框一一樣,代表UI操作與name有bind,但是若是按下設值按鈕再按下取值按鈕會發現,只有文字框二有改變。




範例四:
  • 修改第二個範例使其UI Bind有作用,並且可直接修改程式並能RefreshUI。
  • 對UI操作可以改變屬性值,而程式修改屬性值可以Refresh UI。

$(window).ready(function(){
var  myViewModel={
    userInfo:({name:ko.observable('maggie'),age:ko.observable(25)})
};

ko.applyBindings(myViewModel);

$('#btn').click(function(){
$('#sp').val(myViewModel.userInfo.name());
});

$('#btn2').click(function(){
myViewModel.userInfo.name("jeffrey");
});
});

<!--DOM -->
<input type="text" data-bind="value:userInfo.name" /></br>
<input id="sp" type="text" disabled="true" /></br>
<input id="btn" type="button" value="顯示目前name數值"/>
<input id="btn2" type="button" value="使用程式修改數值"/>

如此,所有bind互動都可正常使用。


範例五:
  • 使用with
  • 對UI操作可以改變屬性值,而程式修改屬性值可以Refresh UI。
$(window).ready(function(){
var  myViewModel={
     userInfo:({name:ko.observable('maggie'),age:ko.observable(25)})
};

ko.applyBindings(myViewModel);

$('#btn').click(function(){
$('#sp').val(myViewModel.userInfo.name());
});

$('#btn2').click(function(){
myViewModel.userInfo.name("jeffrey");
});
});


<!--DOM-->
<div data-bind="with:userInfo">
<input type="text" data-bind="value:name" /></br>
<input id="sp" type="text" disabled="true" /></br>
<input id="btn" type="button" value="顯示目前name數值"/>
<input id="btn2" type="button" value="使用程式修改數值"/>
</div>

note:可以的話就使用with吧,因為input上的data-bind宣告會相對簡潔,缺點在DOM上會多一層標籤包覆。




knockoutjs 6 Computed Observables

Knockoutjs Computed Observables

Q:
    如果你的ViewModel裡有兩個Observable屬性,分別為firstName與lastName,但若你想顯示的是fullName呢?

如何顯示羅羅亞·索隆?
var myViewModel() {
      firstName: = ko.observable('索隆');
      lastName: = ko.observable('羅羅亞');
}


A:
 
  使用computed Observables

Computed Observable

$(window).ready(function (){

var myViewModel = {
firstName: ko.observable('索隆'),
lastName: ko.observable('羅羅亞'),
fullName: null
};

myViewModel.fullName = ko.computed(function(){
return myViewModel.firstName() + '·' + myViewModel.lastName();
},myViewModel);

ko.applyBindings(myViewModel);

});


Bind
全名:<span data-bind="text:fullName"></span>

結果:
全名:索隆·羅羅亞

Note:Ko.computed的第二個參數使用了 myViewModel ,若沒有這個值,computed將無法使用firstName與lastName兩個參考,這是javascript範圍域的關係,第二個參數需要傳入想被computed操作的物件參考。




使用JQuery來改變firstName:

$('#btn').click(function(){
myViewModel.firstName('阿隆索');
});

DOM上增加一個input:


全名:<span data-bind="text:fullName"></span></br>
     <input id="btn" type="button" value="更改firstName"/>


click button後結果:
全名:阿隆索·羅羅亞 

Note:computed observables依賴於一個或多個其它的observables,當所依賴的observable發生變化,computed observables也會跟著更新。


Q:
    那這只有讀取,那寫入呢?


具有write功能的computed
$(window).ready(function(){
function MyViewModel() {
   this.firstName = ko.observable('索隆');
   this.lastName = ko.observable('羅羅亞');     
   this.fullName = ko.computed({
       read: function () {
           return this.firstName() + "·" + this.lastName(); 
       },
       write: function (value) {             
                    //以點號為基準來拆解
           var lastSpacePos = value.lastIndexOf('·');
           if(lastSpacePos > 0) { 
//拆解字串取回firstName
this.firstName(value.substring(0, lastSpacePos));
                       //拆解字串取回lastName
              this.lastName(value.substring(lastSpacePos + 1));
           }
       },
       owner: this
   });

        //啟動knockoutjs的bind功能
ko.applyBindings(new MyViewModel());
});

DOM

<span data-bind="text:firstName"></span></br>
<span data-bind="text:lastName"></span></br>
<input type="text" data-bind="value:fullName"/>

結果:






一開始呈現了 [索隆·羅羅亞],當再輸入框中輸入[蒙其D·魯夫],在span中所bind的firstName與lastName會自動改變,由於這個範例使用點號作字串拆解依據,所以輸入時需使用·號做區隔。

knockoutjs 5 屬性讀取與寫入

knockoutjs Reading and writing observables

<!DOCTYPE html>
<html>
<head>
<title>屬性讀取與寫入</title>
<meta charset="UTF-8"/>
<script src="../lib/jquery-1.7.1.min.js"></script>
<script src="../lib/knockout-2.1.0.js"></script>
<script>
$(window).ready(function (){
var cats = [{name:'咕嘰',age:1,breed:'美國短毛'},
                    {name:
'斯諾',age:1,breed:'米克斯'}];

var dog = {name:"汪汪",age:2,breed:'邊境牧羊'};
var brid = {name:"金金",age:3,breed:'太陽鸚鵡'};
//VM
var myViewModel = {
   cats: ko.observableArray(cats),
   dog : ko.observable(dog),
    bird: ko.observable(brid),
    fish: ko.observable(),
    bug: ko.observable(),
    horse:ko.observable(),  
    showName:ko.observable()
};
       
//啟動綁定
ko.applyBindings(myViewModel);

//連續wirte
myViewModel.fish({name:"尼莫",age:1,breed:"小丑魚"}).bug([{name:"爆爆",age:0,breed:"獨角仙"}]);
//單獨wirte
myViewModel.horse({name:"赤兔",age:2,breed:"汗血寶馬"});
//屬性讀取
var horseName = myViewModel.horse().name;
//寫入
myViewModel.showName(horseName);


});
</script>
</head>
<body>
貓咪:
<div data-bind="foreach:cats" style="margin-bottom: 10px">
名子:<span data-bind="text:name" style="margin-right: 8px"></span>
年齡:<span data-bind="text:age" style="margin-right: 8px"></span>
品種:<span data-bind="text:breed" style="margin-right: 8px"></span></br>
</div>
小狗:
<div style="margin-bottom: 10px">
名子:<span data-bind="text:dog().name" style="margin-right: 8px"></span>
年齡:<span data-bind="text:dog().age" style="margin-right: 8px"></span>
品種:<span data-bind="text:dog().breed" style="margin-right: 8px"></span>
</div>
小鳥:
<div data-bind="with:bird" style="margin-bottom: 10px">
名子:<span data-bind="text:name" style="margin-right: 8px"></span>
年齡:<span data-bind="text:age" style="margin-right: 8px"></span>
品種:<span data-bind="text:breed" style="margin-right: 8px"></span>
</div>
魚仔:
<div data-bind="with:fish" style="margin-bottom: 10px">
名子:<span data-bind="text:name" style="margin-right: 8px"></span>
年齡:<span data-bind="text:age" style="margin-right: 8px"></span>
品種:<span data-bind="text:breed" style="margin-right: 8px"></span>
</div>
小蟲:
<div data-bind="foreach:bug" style="margin-bottom: 10px">
名子:<span data-bind="text:name" style="margin-right: 8px"></span>
年齡:<span data-bind="text:age" style="margin-right: 8px"></span>
品種:<span data-bind="text:breed" style="margin-right: 8px"></span>
</div>
寶馬:
<div data-bind="with:horse" style="margin-bottom: 10px">
名子:<span data-bind="text:name" style="margin-right: 8px"></span>
年齡:<span data-bind="text:age" style="margin-right: 8px"></span>
品種:<span data-bind="text:breed" style="margin-right: 8px"></span>
</div>
Show Name:
<div data-bind="text:showName"></div>
</body>
</html>

執行結果:

貓咪:

名子:咕嘰 年齡:1 品種:美國短毛
名子:斯諾 年齡:1 品種:米克斯
小狗:
名子:汪汪 年齡:2 品種:邊境牧羊
小鳥:
名子:金金 年齡:3 品種:太陽鸚鵡
魚仔:
名子:尼莫 年齡:1 品種:小丑魚
小蟲:
名子:爆爆 年齡:0 品種:獨角仙
寶馬:
名子:赤兔 年齡:2 品種:汗血寶馬
Show Name:
赤兔