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

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

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

  • 相关阅读:
    CodeForces 681D Gifts by the List (树上DFS)
    UVa 12342 Tax Calculator (水题,纳税)
    CodeForces 681C Heap Operations (模拟题,优先队列)
    CodeForces 682C Alyona and the Tree (树上DFS)
    CodeForces 682B Alyona and Mex (题意水题)
    CodeForces 682A Alyona and Numbers (水题,数学)
    Virtualizing memory type
    页面跳转
    PHP Misc. 函数
    PHP 5 Math 函数
  • 原文地址:https://www.cnblogs.com/duyao/p/4362895.html
Copyright © 2020-2023  润新知