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

KnockoutJS: Update/Insert data to a viewModel using mapping

本文关键字:更新 插入 viewModel 数据 映射 KnockoutJS      更新时间:2023-09-26

我已经想了很长一段时间了。我找不到任何能解决这个问题的东西,但如果我错了,请纠正我。

问题是:我有来自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);​

Fiddle:http://jsfiddle.net/mikaelbr/gDjA7/

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

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

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

在更新时(在我的例子中是WebSocket消息),我循环浏览模型,更改有问题项的内容,并使用方法valueHasMutted()向Knockout lib发出更改值的通知。

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

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

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

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

使用updateFromJS是在应该添加值时替换值

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