zoukankan      html  css  js  c++  java
  • Knockout.Js案例二Working With Lists And Collections

    案例一:Foreach绑定

    通常,您要生成重复的UI元素,特别是当显示列表,用户可以添加和删除元素。KO.JS让你轻松,使用的数组和foreach绑定。

    在接下来的几分钟,您将构建一个动态UI保留席位和吃饭——这可能是一个一步一个机票预订过程。在右下方的窗格中,您已经有了:

    HTML:

     <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:

     function SeatReservation(nameinitialMeal{

        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)"price34.95 },
            mealName"Ultimate (whole zebra)"price290 }
        ];    

        // 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表示,通过使用使绑定:

    按钮时座位限制成了残疾。你不必编写任何代码重新启用它,当用户删除一些席位(搞乱你的“删除”逻辑),因为表达式将自动重新评估相关数据变化时所击倒。

    最后:如果你想学习的方法保存回服务器更新数据,看教程的加载和保存数据。

  • 相关阅读:
    使用karma和jasmine进行angularjs单元测试
    NHibernate之(23):探索NHibernate二级缓存(上)
    NHibernate之(22):探索NHibernate一级缓存
    NHibernate之(21):探索对象状态
    NHibernate之(20):再探SchemaExport工具使用
    NHibernate之(19):初探SchemaExport工具使用
    NHibernate之(18):初探代码生成工具使用
    NHibernate之(17):探索NHibernate中使用存储过程(下)
    NHibernate之(16):探索NHibernate中使用存储过程(中)
    NHibernate之(15):探索NHibernate中使用存储过程(上)
  • 原文地址:https://www.cnblogs.com/duyao/p/4362895.html
Copyright © 2011-2022 走看看