淘汰赛的映射打破了可观察的数组 [英] Knockout's mapping breaks observable arrays

查看:51
本文介绍了淘汰赛的映射打破了可观察的数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用Knockout的映射插件时遇到了一个奇怪的问题.

I'm experiencing a strange problem with Knockout's mapping plug-in.

如果我通过映射填充了一个可观察的数组,那么即使UI正确更新,我也无法迭代该数组或获取其长度,该数组似乎为空.

If I fill an observable array through mapping I can't iterate the array or get its length, even though the UI is updated correctly, the array seems empty.

您可以在此处找到有效的jsFiddle: http://jsfiddle.net/VsbsC/

You can find a working jsFiddle here: http://jsfiddle.net/VsbsC/

这是HTML标记:

<p><input data-bind="click: load" type="button" value="Load" /></p>
<p><input data-bind="click: check" type="button" value="Check" /></p>
<table>
    <tbody data-bind="foreach: items">
        <tr>
            <td data-bind="text: name"></td>
            <td data-bind="text: value"></td>
        </tr>
    </tbody>
</table>
<p data-bind="text: total"></p>

这是JavaScript代码:

This is the JavaScript code:

var ViewModel = function () {
    var self = this;
    self.items = ko.observableArray();
    self.load = function () {
        self.items([
            { "name": "joey", "value": 1 },
            { "name": "anne", "value": 2 },
            { "name": "paul", "value": 3 },
            { "name": "mike", "value": 4 }
        ]);
    };
    self.check = function () {
        alert(self.items().length);
    };
    self.total = ko.computed(function () {
        var total = 0;
        for (var i = 0; i < self.items().length; i++) {
            total += self.items()[i].value;
        }
        return total;
    });
};
var viewModel = new ViewModel();
ko.applyBindings(viewModel);

当我点击 Load 按钮时,记录和总数都将正确显示,而当我点击 Check 按钮时,我将获得正确的商品编号.

When I click on the Load button both the records and the total are displayed correctly, and when I click the Check button I get the correct item number.

但是,如果我改变了

self.items([
    { "name": "joey", "value": 1 },
    { "name": "anne", "value": 2 },
    { "name": "paul", "value": 3 },
    { "name": "mike", "value": 4 }
]);

self.items(ko.mapping.fromJS([
    { "name": "joey", "value": 1 },
    { "name": "anne", "value": 2 },
    { "name": "paul", "value": 3 },
    { "name": "mike", "value": 4 }
]));

UI仍然可以正确呈现,但是总数显示为零,单击 Check 也会产生零,并且console.info -ing self.items会产生一个空数组.

the UI still get rendered correctly, but the total shows zero, clicking Check yields zero too, and console.info-ing self.items yields an empty array.

这怎么可能?我已经无数次地重新阅读了这些教程,但我不明白自己在做什么错.

How is this possible? I've re-read the tutorials countless times, and I can't understand what I'm doing wrong.

P.s.我需要通过映射插件填充可观察数组,因为在实际页面中,值来自AJAX请求.

P.s. I need to fill the observable array through the mapping plug-in because in the real page the values are coming from an AJAX request.

推荐答案

您看到的问题基于以下事实:如果给定映射数组,则映射插件将创建一个observableArray.因此,您正在将self.items observableArray的值设置为等于observableArray(而不只是一个数组).因此,它被包装了额外的时间.

The issue that you are seeing is based on the fact that the mapping plugin will create an observableArray if it is given an array. So, you are setting the value of the self.items observableArray equal to an observableArray (rather than just an array). So, it is wrapped an extra time.

这是一种实现方法:

var ViewModel = function () {
    var self = this;
    self.items = ko.mapping.fromJS([]);
    self.load = function () {
        ko.mapping.fromJS([
            { "name": "joey", "value": 1 },
            { "name": "anne", "value": 2 },
            { "name": "paul", "value": 3 },
            { "name": "mike", "value": 4 }
        ], self.items);
    };
    self.check = function () {
        alert(self.items().length);
    };
    self.total = ko.computed(function () {
        var total = 0, items = self.items();
        for (var i = 0; i < items.length; i++) {
            total += items[i].value();
        }
        return total;
    });
};
var viewModel = new ViewModel();
ko.applyBindings(viewModel);

因此,您可以使用映射插件初始化原始的observableArray,以便随时进行更新.然后,在更新时,调用ko.mapping.fromJS,其中包含更新的数据和要更新的映射对象.

So, you initialize the original observableArray using the mapping plugin, so it is ready to be updated. Then, on the update you call ko.mapping.fromJS with the updated data and the the mapped object to update.

此时的另一个较小更改就是在计算的可观察对象中使用value(),因为它是映射插件中的可观察对象.

The other minor change at that point was just to use value() in your computed observable now that it is an observable from the mapping plugin.

此处提供示例: http://jsfiddle.net/rniemeyer/3La5K/

这篇关于淘汰赛的映射打破了可观察的数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆