6

我一直试图弄清楚这一点已经有一段时间了。我找不到任何解决此问题的方法,但如果我错了,请纠正我。

问题:我有来自 JSON API 的数据,带有嵌套的数组/对象结构。我使用映射最初用我的数据填充模型。为了更新这一点,我想在新数据到达时扩展模型,或者更新现有数据。

据我所知,映射选项键应该为我做这个技巧,但我可能误解了映射选项的功能。

我已经把这个例子所代表的问题归结为:

var userMapping = {
    key: function(item) {
        return ko.utils.unwrapObservable(item.id);
    }
};

// JSON call replaced with values
var viewModel = {
    users: ko.mapping.fromJS([], userMapping)
};

// Should insert new - new ID?
ko.mapping.fromJS([{"id":1,"name":"Foo"}, {"id":2,"name":"Bar"}], userMapping, viewModel.users);

// Should only update ID#1 - same ID?
ko.mapping.fromJS([{"id":1,"name":"Bat"}], userMapping, viewModel.users);

// Should insert new - New ID?
ko.mapping.fromJS([{"id":3,"name":"New"}, {"id":4,"name":"New"}], userMapping, viewModel.users);

ko.applyBindings(viewModel);​

小提琴:http: //jsfiddle.net/mikaelbr/gDjA7/

如您所见,第一行插入数据。都好。但是当我尝试更新时,它会替换内容。第三个映射也一样;它替换了内容,而不是扩展它。

我用错了吗?我应该在使用映射之前尝试“手动”扩展内容吗?

编辑解决方案:
我通过使用第二个辅助数组存储所有当前模型解决了这种情况。在新数据上,我扩展了这个数组,并更新了视图模型以包含累积的项目。

在更新时(在我的例子中是 WebSocket 消息),我遍历模型,更改了相关项目的内容,并使用方法 valueHasMutated() 将更改的值通知 Knockout 库。

4

3 回答 3

4

通过查看您的示例代码,映射插件的行为完全符合我的预期。当您调用fromJS一个集合时,您实际上是在告诉映射插件这是该集合的新内容。例如:

在第二行,它如何知道您是在更新还是只是删除了 id:2?

I can't find any mention of a suitable method that treats the data as simply an update, although you could add one. Mapped arrays come with some helpful methods such as mappedIndexOf to help you find particular items. If you receive an update data set simply loop through it, find the item and update it with a mapping.fromJS call to that particular item. This can easily be generalized into reusable method.

于 2012-03-09T17:05:25.673 回答
1

您可以使用ko.mapping.updateFromJS()来更新现有值。但是,它不会添加新值,因此这将是您的实例中的一个问题。请查看下面的链接以获取更多详细信息。

使用 updateFromJS 正在替换应该添加的值

于 2012-03-09T16:43:38.023 回答
0

是的,您应该首先将所有数据收集到一个列表或数组中,然后将映射应用于该列表。否则,您将覆盖 viewModel 中的值。

于 2012-03-09T15:52:12.267 回答