在Knockoutjs中设置计算对象的observableArray的更好方法

A better way to set up observableArray of computed objects in Knockoutjs

本文关键字:observableArray 更好 方法 对象 计算 Knockoutjs 设置      更新时间:2023-09-26

在这个jsfiddle中,我有一个简单的例子来说明我想做什么。一切都很好。但似乎必须有一种更好的方法来创建这些带有循环之类的数组。我试了一整天都没有成功。有人能告诉我

  1. 有可能
  2. 我需要表演什么巫毒才能发挥作用

这是小提琴的密码。

视图:

<table>
<tbody>
    <tr>
        <td></td>
        <!-- ko foreach: topvals -->
        <td >
            <input type="text" data-bind="value: val"/>
        </td>
        <!-- /ko -->
    </tr>
    <tr>
        <td><input type="text" data-bind="value:sidevals()[0].val"/></td>
        <!-- ko foreach: intersections()[0] -->
        <td><span data-bind="text: val"></span></td>
        <!-- /ko -->
    </tr>
    <tr>
        <td ><input type="text" data-bind="value:sidevals()[1].val"/></td>
        <!-- ko foreach: intersections()[1] -->
        <td><span data-bind="text: val"></span></td>
        <!-- /ko -->
    </tr>
</tbody>
</table>

视图模型:

function ViewModel() {
    this.topvals = ko.observableArray([
        { val: ko.observable(6) },
        { val: ko.observable(1) },
        { val: ko.observable(1) },
        { val: ko.observable(1) }
    ]);
    this.sidevals = ko.observableArray([
        { val: ko.observable(1) },
        { val: ko.observable(1) },
        { val: ko.observable(1) }
    ]);
    this.intersections = ko.observableArray([
        [
            { val: ko.computed(function () { return this.topvals()[0].val() * this.sidevals()[0].val(); }, this) },
            { val: ko.computed(function () { return this.topvals()[1].val() * this.sidevals()[0].val(); }, this) },
            { val: ko.computed(function () { return this.topvals()[2].val() * this.sidevals()[0].val(); }, this) },
            { val: ko.computed(function () { return this.topvals()[3].val() * this.sidevals()[0].val(); }, this) }
        ],
        [
            { val: ko.computed(function () { return this.topvals()[0].val() * this.sidevals()[1].val(); }, this) },
            { val: ko.computed(function () { return this.topvals()[1].val() * this.sidevals()[1].val(); }, this) },
            { val: ko.computed(function () { return this.topvals()[2].val() * this.sidevals()[1].val(); }, this) },
            { val: ko.computed(function () { return this.topvals()[3].val() * this.sidevals()[1].val(); }, this) }
        ]
    ]);
}
ko.applyBindings(new ViewModel());
  • 要创建topvalssidevals数组,可以使用ko.mapping.fromJS
  • 要创建计算的intersections,可以使用ko.utils.arrayMap函数返回一个"数组数组"

这是最后的代码(还有一个jsfiddle):

function ViewModel() {
    var self = this;
    var calculateIntersection = function(topval, sideval) {
        return topval * sideval;
    };
    var topvals = [{ val: 1 }, { val: 2 }, { val: 3 }];
    var sidevals = [{ val: 1 }, { val: 2 }, { val: 3 }];
    self.topvals = ko.mapping.fromJS(topvals);
    self.sidevals = ko.mapping.fromJS(sidevals);
    self.intersections = ko.computed(function() {
        return ko.utils.arrayMap(self.sidevals(), function(sideval) {
            return ko.utils.arrayMap(self.topvals(), function(topval) {
                return calculateIntersection(topval.val(), sideval.val());
            });
        });
    });
}
ko.applyBindings(new ViewModel());

以下是观点:

<table>
    <tbody>
        <tr>
            <td></td>
            <!-- ko foreach: topvals -->
            <td >
                <input type="text" data-bind="value: val"/>
            </td>
            <!-- /ko -->
        </tr>
        <!-- ko foreach: sidevals -->
        <tr>
            <td><input type="text" data-bind="value: val"/></td>
            <!-- ko foreach: $root.intersections()[$index()] -->
            <td><span data-bind="text: $data"></span></td>
            <!-- /ko -->
        </tr>
        <!-- /ko -->
    </tbody>
</table>

这个简单的视图模型已经做到了:

function ViewModel(vals1, vals2) {
    this.topvals = ko.observableArray(mapToObservables(vals1));
    this.sidevals = ko.observableArray(mapToObservables(vals2));
    this.calc = function (val1, val2) {
        return ko.unwrap(val1) * ko.unwrap(val2);
    };
}
ko.applyBindings(new ViewModel([6, 5, 4, 3], [1, 2, 3]));

其中mapToObservables代表映射插件或类似以下的函数:

function mapToObservables(vals) {
    return ko.utils.arrayMap(vals, function (val) {
        return { val: ko.observable(val) };
    });
};

和这个视图

<table>
<tbody>
    <tr>
        <td></td>
        <!-- ko foreach: topvals -->
        <td><input type="text" data-bind="value: val"/></td>
        <!-- /ko -->
    </tr>
    <!-- ko foreach: sidevals -->
    <tr>
        <td><input type="text" data-bind="value: val"/></td>
        <!-- ko foreach: $root.topvals -->
        <td><span data-bind="text: $root.calc(val, $parent.val)"></span></td>
        <!-- /ko -->
    </tr>
    <!-- /ko -->
</tbody>
</table>

请参阅:http://jsfiddle.net/dt9kL/

一种变体是对以下值使用单独的子模型:http://jsfiddle.net/dt9kL/1/.对于封装单个值来说,这是过分的,但对于更复杂的结构可能有用。