Knockout.Js案例二Working With Lists And Collections

案例一:Foreach綁定html

一般,您要生成重複的UI元素,特別是當顯示列表,用戶能夠添加和刪除元素。KO.JS讓你輕鬆,使用的數組和foreach綁定。數組

 

在接下來的幾分鐘,您將構建一個動態UI保留席位和吃飯——這多是一個一步一個機票預訂過程。在右下方的窗格中,您已經有了:服務器

HTML:app

 <h2>Your seat reservations</h2>框架

< table >
     < thead > < tr >
         < th > Passenger name </ th > < th > Meal </ th > < th > Surcharge </ th > < th > </ th >
     </ tr > </ thead >
     <!-- Todo: Generate table body -->
    < tbody  data-bind = "foreach: seats" >
     < tr >
         < td  data-bind = "text: name" > </ td >
         < td  data-bind = "text: meal().mealName" > </ td >
         < td  data-bind = "text: meal().price" > </ td >

    </tr>編輯器

   </tbody>函數

</table>學習

 

JS:ui

 function SeatReservation(nameinitialMeal{this

     var  self  this ;
     self . name  name ;
     self . meal  ko . observable ( initialMeal ) ;
}

SeatReservation,一個簡單的JS的數,選擇存儲乘客名字和一頓飯

 function ReservationsViewModel({

     var  self  this ;

     // Non-editable catalog data - would come from the server
     self . availableMeals  [
         mealName "Standard (sandwich)" price } ,
         mealName "Premium (lobster)" price 34.95  } ,
         mealName "Ultimate (whole zebra)" price 290  }
     ] ;    

     // Editable data
     self . seats  ko . observableArray ( [
         new  SeatReservation ( "Steve" self . availableMeals [ 0 ] ) ,
         new  SeatReservation ( "Bert" self . availableMeals [ 0 ] )
     ] ) ;
}

ko.applyBindings(new ReservationsViewModel());

 

ReservationsViewModel:viewmodel類:

availableMeals: js對象提供餐數據,

seat:數組初始SeatReservation實例的集合。

請注意,這是一個observableArray——絕不奇怪,可見至關於一個常規數組中,這意味着它能夠自動觸發更新UI項添加或刪除。


Notice that, because the meal property is an observable, it's important to invoke meal()as a function (to obtain its current value) before attempting to read sub-properties. In other words, write meal().pricenot meal.price.

請注意,由於這頓飯屬性是一個可觀察到的,是很重要的()做爲一個函數來調用餐(得到其當前值)以前sub-properties閱讀。換句話說,寫餐()。的價格,而不是meal.price。由於字段是能夠觀察到的,是很重要的,因此須要();

 

foreach is part of a family of control flow bindings that includes foreachififnot, and with. These make it possible to construct any kind of iterative, conditional, or nested UI based on your dynamic viewmodel.

foreach屬於控制流綁定的一部分。這讓咱們構造任何類型的迭代,條件,或嵌套的基於動態viewmodel的UI

 

 

 案例2:Add Item新增項

 MVVM模式後使它很是簡單的使用數組和層次等多變的對象圖。你更新基礎數據,UI自動更新同步。


實現增長座位預訂:

添加一個按鈕到視圖,使用點擊綁定關聯與函數在你點擊視圖模型:

 <button data-bind="click: addSeat">Reserve another seat</button>

而後實現addSeat函數,使其推進額外進入座位數組:

 

function ReservationsViewModel() {
     var self =  this;

     //  Non-editable catalog data - would come from the server
    self.availableMeals = [
        { mealName: "Standard (sandwich)", price: 0 },
        { mealName: "Premium (lobster)", price: 34.95 },
        { mealName: "Ultimate (whole zebra)", price: 290 }
    ];    

     //  Editable data
    self.seats = ko.observableArray([
         new SeatReservation("Steve", self.availableMeals[0]),
         new SeatReservation("Bert", self.availableMeals[0])
    ]);
     self.addSeat =  function() {
        self.seats.push( new SeatReservation("", self.availableMeals[0]));
    }

} 

 試一試,如今當你點擊「預訂另外一個座位」,UI更新以匹配。這是由於座位是可觀察到的數組,因此添加或刪除條目將自動觸發更新UI。

 注意,添加一行不涉及再生整個UI。爲了提升效率,KO.JS跟蹤改變在你的視圖模型,並執行DOM更新以匹配的最小集合。這意味着您能夠擴大規模很是大或複雜的ui,甚至它能夠保持時髦和響應在低端移動設備.

 

 

案例三:使數據能夠編輯

你可使用綁定在foreach塊和其餘地方同樣,因此很容易升級咱們進入一個完整的數據編輯器。更新您須要的東西:

 <tbody data-bind="foreach: seats">

    <tr>
        <td><input data-bind="value: name" /></td>
        <td><select data-bind="options: $root.availableMeals, value: meal, optionsText: 'mealName'"></select></td>
        <td data-bind="text: meal().price"></td>
    </tr>    
</tbody>  
這段代碼使用了兩個新的綁定,選項和optionsText,一塊兒控制兩組可用的項目在一個下拉列表,和對象屬性(在本例中,mealName)是用來表示屏幕上的每一項

 如今試一試,你能夠選擇從可用的飯菜,和這樣作會致使相應的行(只)刷新顯示,飯菜的價格。

 

格式化Prices


 咱們有一個不錯的面向對象的表示咱們的數據,因此咱們能夠平凡地添加額外的屬性和函數對象圖的任何地方。讓咱們給SeatReservation類格式的能力本身的價格數據使用一些自定義的邏輯。

   1function SeatReservation(name, initialMeal) {

 2      var self =  this;
 3     self.name = name;
 4     self.meal = ko.observable(initialMeal);
 5 
 6     self.formattedPrice = ko.computed( function() {
 7          var price = self.meal().price;
 8          return price ? "$" + price.toFixed(2) : "None";        
 9     });
10 }  
如今你能夠更新視圖使用了formattedPrice每一個SeatReservation實例:  

 

因爲格式化的價格將計算基於所選餐,咱們可使用ko.computed表明(所以它將自動更新時餐選擇更改):
function SeatReservation(name, initialMeal) {
     var self =  this;
    self.name = name;
    self.meal = ko.observable(initialMeal);

    self.formattedPrice = ko.computed( function() {
         var price = self.meal().price;
         return price ? "$" + price.toFixed(2) : "None";        
    });
}

 如今你能夠更新視圖使用了formattedPrice每一個SeatReservation實例:

1 <tr>
2     <td><input data-bind="value: name" /></td>
3     <td><select data-bind="options: $root.availableMeals, value: meal, optionsText: 'mealName'"></select></td>
4     <td data-bind="text: formattedPrice"></td>

5 </tr> 

 

 案例四:刪除項目和總和

 由於你能夠添加條目,您應該可以刪除它們,對嗎?如您所料,這只是一個更新底層數據的問題。      

更新你的視圖,它顯示每一個條目旁邊的「刪除」連接

<tr>
    <td><input data-bind="value: name" /></td>
    <td><select data-bind="options: $root.availableMeals, value: meal, optionsText: 'mealName'"></select></td>
    <td data-bind="text: formattedPrice"></td>
    <td><a href="#" data-bind="click: $root.removeSeat">Remove</a></td>

</tr>       

注意,$ root。前綴致使KO.JS尋找removeSeaf方法在你的頂層視圖模型而不是SeatReservation實例綁定——這是一個更方便的地方把removeSeat這個例子。

所以,添加相應的removeSeat函數根viewmodel類,ReservationsViewModel:

 1 function ReservationsViewModel() {

2      //  ... leave the rest unchanged ...
3 
4      //  Operations
5      self.addSeat =  function() {  /*  ... leave unchanged ...  */ }
6     self.removeSeat =  function(seat) { self.seats.remove(seat) }
7 }   

 如今,若是你運行應用程序時,您將可以刪除物品以及添加它們。

 

顯示一個總附加費:
最好是讓客戶知道他們要支付,對嗎?絕不奇怪,咱們能夠定義爲一個計算的屬性,讓框架照顧知道何時從新計算並刷新顯示。      

添加如下ko.computed ReservationsViewModel內:

 

1 self.totalSurcharge = ko.computed( function() {
2     var total = 0;
3     for ( var i = 0; i < self.seats().length; i++)
4        total += self.seats()[i].meal().price;
5     return total;
6 });


再次注意,由於座椅和飯均可見,咱們調用函數來讀他們的當前值(例如self.seats(). length)。

顯示所有附加費經過添加如下< h3 >元素

 <h3 data-bind="visible: totalSurcharge() > 0">

    Total surcharge: $<span data-bind="text: totalSurcharge().toFixed(2)"></span>
</h3>

這段代碼演示了兩個點:      

可見綁定使有形或無形的元素做爲數據更改(在內部,它修改元素的CSS顯示樣式)。在本例中,咱們選擇只顯示「總附加費」信息若是是大於零。   

您可使用任意JavaScript表達式內部聲明式綁定。在這裏,咱們使用totalSurcharge()> 0和totalSurcharge().toFixed(2)。在內部,這實際上定義了一個屬性來表示的輸出,計算表達式。它只是一個很是輕量級的和方便的語法的選擇。

 

如今,若是你運行代碼,您將看到「總附加費」出現和消失,因爲依賴跟蹤,它知道何時從新計算本身的價值——你不須要任何代碼在你的「增長」或「刪除」功能,迫使依賴手動更新。

 

最後的細節:

隨着MVVM模式,UI的一個面向對象的表示的數據和行爲,你在一個好位置灑在額外的行爲在一個很是天然和方便的方式。

例如,若是你要求顯示的總數預留座位,您能夠實如今一個地方,你不須要寫任何額外代碼以使座位數量更新當你添加或刪除條目。只是更新< h2 >頂部的觀點:

1 <h2>Your seat reservations (<span data-bind="text: seats().length"></span>)</h2> 

 

一樣,若是你要求限制數量的席位能夠儲備,說,可使UI表示,經過使用使綁定:

按鈕時座位限制成了殘疾。你沒必要編寫任何代碼從新啓用它,當用戶刪除一些席位(搞亂你的「刪除」邏輯),由於表達式將自動從新評估相關數據變化時所擊倒。

 

最後:若是你想學習的方法保存回服務器更新數據,看教程的加載和保存數據。

相關文章
相關標籤/搜索