2012年8月13日 星期一

knockoutjs 4 偵聽屬性變動與移除

Knockoutjs ViewModel屬性變動偵聽與移除
  • 加入偵聽 
    var  mysubscription = myViewModel.userName.subscribe(
    function(newValue){
         //屬性變動時要做的處理
    });
  • 移除屬性偵聽
    mysubscription.dispose();
example:
<!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 companysInfo = [
  {name:"Apple",twName:"蘋果"} , 
    {name:"HTC",twName:"宏達電"} ,
    {name:"Samsung",twName:"三星"}];    
   
var defaultName = companysInfo[0].twName;
$('#enName').html(companysInfo[0].name);

var myViewModel = {
   userName : ko.observable(defaultName),
   companys:ko.observableArray(companysInfo)
};

//加上偵聽
var mysubscription = myViewModel.userName.subscribe(function(newValue) {  
  for(var i in myViewModel.companys()){
                        //如果比較相同,就將英文名稱換掉
  (myViewModel.companys()[i].twName == newValue 
  && $('#enName').html(myViewModel.companys()[i].name));
  }
});

//設定ko綁定
ko.applyBindings(myViewModel);

//select changed
$('#companys').change(function(){
myViewModel.userName(myViewModel.companys()[this.value].twName);
});


//移除屬性變動偵聽
$('#btn').click(function(){
mysubscription.dispose();
});
});
</script>
</head>
<body>
中文:<span data-bind="text:userName"></span></br>
英文:<span id="enName"></span>
<div>
<select id="companys" data-bind="foreach:companys">
<option data-bind="text:name , value:$index"></option>
</select>
</div>
<input id="btn" type="button" value="移除屬性變動偵聽" />
</body>
</html>

Knockoutjs 3 ko.applyBindings()

Ko.applyBindings()
  • 第一個參數 : 表示你想用來綁定的ViewModel對象。
  • 第二個參數 : 選用的,要data-bind的HTML DOM元素。
    例如:
    ko.applyBindings(myViewModel ,
    document.getElementById('someElementId'));
     
    它現在是只有作為someElementId 的元素和子元素才能激活KO功能。好處是你可以在同一個頁面聲明多個view model,用來區分區域。
example:


$(document).ready(function(){
var visableContainer = document.getElementById('boxA');
        //指定作用的容器
ko.applyBindings(new MyViewModel() , visableContainer );
});

function MyViewModel(){
this.personName = ko.observable('Bob');
this.personAge = ko.observable(123);    
}

<div id="boxA">
The name is <span data-bind="text: personName"></span></br>
The name is <span data-bind="text: personName"></span></br>
</div>
</br>
<div id="box">
The Age is <span data-bind="text: personAge"></span></br>
The Age is <span data-bind="text: personAge"></span></br>
</div>

結果:
 The name is Bob
 The name is Bob

Note:這裡ko只bind在id為boxA的元素容器,html上的data-bind只是宣告聲明給予ko作bind時能找著目標,實際bind是使用 ko.applyBindings()來實作。

Knockoutjs 2 MVVM

Knockoutjs使用MVVM設計模式
  • Model:
        在client serve並使用ajax技術的架構中,為負責ajax remote部分,並儲存從遠端API取回的原始資料,在非使用ajax架構中則是負責商業邏輯部分。
  • ViewModel (VM):
        View與Model溝通的橋接,knockoutjs中ViewModel與View之間會綁定(bind),若再替VM中的屬性加上觀察者(Observables),即可在屬性變動時更新被bind的UI元素。
  • View:
        顯示元件,knockoutjs中的View對象就是HTML元素。


建立一個ViewModel (Create ViewModel):

var myViewModel = {
    userName: 'maggie',
    userAge: 25,
    height: 165
};

這個ViewMode還未使用到Observables,所以只會更新一次,之後屬性被改變,都不會更新UI。

設置View Bind對象宣告:
姓名:<span data-bind="text: userName"></span></br>
年齡:<span data-bind="text: userAge"></span></br>
身高<span data-bind="text: height"></span>


執行knockoutjs榜定:
ko.applyBindings(myViewModel);

變更userName:
MyViewModel.userName = "小J";

程式執行結果:
姓名:maggie
年齡:25
身高:165

Note:由執行結果中可見,雖然屬性被改變,但是View並未Refresh,這是因為ViewModel內的屬性還未使用 Observables。


使用Observables:

var myViewModel = {
    userName : ko.observable('maggie'),
    userAge : ko.observable(25),
    height : ko.observable(165)
};

ko.applyBindings(myViewModel);

myViewModel.userName("小J");
myViewModel.userAge(34);
myViewModel.height(168);


使用觀察者模式後的執行結果:
姓名:小J
年齡:34
身高:168 


Note:注意使用Observables模式,屬性對象將變成一個function,因此屬性值改變會是,myViewModel.userName("小J")。



Knockouts 1 簡介

knockoutjs 
特性:
  • Elegant dependency tracking (優雅的依賴跟蹤):
        當你的data model改變時,都會自動更新對應UI。
  • Declarative bindings (宣告綁定):
        簡易的方式將你的UI與Data Model建立關聯(bindings)。
  • Trivially extensible (容易擴展):
        只需要幾行代碼即可實現自訂行為作為新的聲明綁定。

好處:
  • Pure Javascript Library :
        純Javascript類別庫,能運行於Server或是Client端。
  • Can be added on top of your existing web application:
        能添加到現行的應用程序中,而不需大架構改變。
  • Compact:
        小巧的,壓縮後只有13kb。
  • Works on any mainstream browser:   
        能運行在任何的主流瀏覽器上(IE 6+, Firefox 2+, Chrome, Safari, others)。
  • Comprehensive suite of specifications (developed BDD-style):   
        採用行為驅動開發 - 意味著在新的瀏覽器與平台上可以容易通過驗證。
核心功能:
  • Observables and dependency tracking:
        當data model改變時能夠自動更新UI。
  • Declarative bindings:
        簡易語法能容易的將model關聯到DOM元素上。
  • Templating:
       使用嵌套模板可以建立複雜的介面。


載入:
    <script type='text/javascript' src='knockout-2.1.0.js'></script>

example:


<!DOCTYPE html>
<html>
<head>
<title>easy example</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>
$(document).ready(function(){
var myViewModel =
{
myData: ko.observableArray([ '一月', '二月', '三月', '四月' ])
};
ko.applyBindings(myViewModel);
});
</script>
</head>
<body>
<ul data-bind="foreach: myData">
   <li>
       <span>當前項目:</span><b data-bind="text: $data"></b>
   </li>
</ul>
第一項為:<span data-bind="text:myData()[0]"></span></br>
陣列長度:<span data-bind="text:myData().length"></span></br>
</body>
</html>


結果:
  • 當前項目: 一月
  • 當前項目: 二月
  • 當前項目: 三月
  • 當前項目: 四月
第一項為:一月
陣列長度:4