淘汰赛 - 可分组阵列(Knockout - groupable array)

2019-10-17 15:23发布

从本教程中,我试图理解这个有前途的框架。 我的问题是如何从观察到的阵列(过滤器)提取一些数据? 我发现了一个类似的quesion这里: 类似的问题

但我不知道如何实现它。 这里是测试: 的jsfiddle

HTML代码:

<h2>Your seat reservations (<span data-bind="text: seats().length"></span>)</h2>
<h4>
Distribution by meal type:
    <table>
        <thead>
            <tr data-bind="foreach: availableMeals">
                <th><span data-bind="text: mealName"></span></th>
            </tr>
        </thead>
        <tbody>
            <tr data-bind="foreach: availableMeals">
                <td>???</td>
            </tr>
        </tbody>
    </table>
</h4>
<table>
    <thead><tr>
        <th>Passenger name</th><th>Meal</th><th>Surcharge</th><th></th>
    </tr></thead>
    <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: formattedPrice"></td>
            <td><a href="#" data-bind="click: $root.removeSeat">Remove</a></td>
        </tr>    
    </tbody>
</table>

<button data-bind="click: addSeat, enable: seats().length < 7">Reserve another seat</button>

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

JS代码:

// extend from the link to the similar question from stackoverflow:
ko.observableArray.fn.distinct = function(prop) {
    var target = this;
    target.index = {};
    target.index[prop] = ko.observable({});    
    //Group by already set up, bail out.
    if (target.index && target.index[prop]) return target;
    ko.computed(function() {
        //rebuild index
        var propIndex = {};

        ko.utils.arrayForEach(target(), function(item) {
            var key = ko.utils.unwrapObservable(item[prop]);
            if (key) {
                propIndex[key] = propIndex[key] || [];
                propIndex[key].push(item);            
            }
        });   

        target.index[prop](propIndex);
    });

    return target;
};

// Class to represent a row in the seat reservations grid
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";        
    });    
}

// Overall viewmodel for this screen, along with initial state
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]),
        new SeatReservation("Steve", self.availableMeals[1]),
        new SeatReservation("John", self.availableMeals[1]),
        new SeatReservation("Frank", self.availableMeals[1]),
        new SeatReservation("Evan", self.availableMeals[2])
    ]);

    // Computed data
    self.totalSurcharge = ko.computed(function() {
       var total = 0;
       for (var i = 0; i < self.seats().length; i++)
           total += self.seats()[i].meal().price;
       return total;
    });    

    // Operations
    self.addSeat = function() {
        self.seats.push(new SeatReservation("", self.availableMeals[0]));
    }
    self.removeSeat = function(seat) { self.seats.remove(seat) }
}

ko.applyBindings(new ReservationsViewModel());

我从KO教程工作:铅是我想要显示的客户由于用餐类型分布?

Answer 1:

开箱即用的淘汰赛不提供任何“可分组阵列”。

然而淘汰赛自带了一些实用功能 ,如:

  • ko.utils.arrayForEach
  • ko.utils.arrayFilter

它可以帮助你手工建立自己的自定义分组。

因此,这里是一个怎么样mealDistribution实现可能是这样的:

self.mealDistribution = ko.computed(function () {
        var seatCount = self.seats().length;
        var result = [];
        ko.utils.arrayForEach(self.availableMeals, function (meal) {
            var mealCount = ko.utils.arrayFilter(self.seats(), function (item) {
                return item.meal() == meal}).length;
            result.push(mealCount / seatCount);

        });
        return result;
    });

演示的jsfiddle 。

如果你想有一些更复杂的阵列处理功能,你应该检出Underscore.js其中有像一些非常好的功能库groupBycountBy



文章来源: Knockout - groupable array