KnockoutJS:使用映射更新/插入数据到viewModel

时间:2012-03-09 15:47:39

标签: javascript knockout.js knockout-mapping-plugin

我一直试图解决这个问题很长一段时间了。我找不到任何解决这个问题的方法,但如果我错了请纠正我。

问题: 我有来自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 lib发出更改值的通知。

3 个答案:

答案 0 :(得分:4)

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

在第二行,怎么知道你是在更新还是只是删除了id:2?

我找不到任何提及将数据视为简单更新的合适方法,尽管您可以添加一个。映射数组附带了一些有用的方法,例如mappedIndexOf,以帮助您查找特定项目。如果您收到更新数据集只需循环遍历它,找到该项并使用mapping.fromJS调用该特定项来更新它。这很容易概括为可重用的方法。

答案 1 :(得分:1)

您可以使用ko.mapping.updateFromJS()更新现有值。但是,它不会添加新值,因此在您的实例中会出现问题。请查看下面的链接了解更多详情。

Using updateFromJS is replacing values when it should be adding them

答案 2 :(得分:0)

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