2

在使用 KO 映射插件更新页面上的数据时,我最近注意到一些有关的事情。我认为第一个现在已在 2.1.1 中修复,下面显示的第二个仍然存在:

我有一个简单的模型。问题在于它包含的地址数组。似乎当我使用映射插件时,它会跟踪数组中的 2 个元素,而实际上只有一个元素。我不确定这是否是我的代码或映射插件的问题。请考虑以下简单示例:

//Retrieved thru AJAX
var serverData = { name: "Bob", Addresses: [{ AddressLine: "", City: "", PostalCode: "", StateID: 10}] };  

    load(serverData);  
    //Seems OK at this point
    //this.vm.__ko_mapping__.mappedProperties shows properties for Addresses[0] & name which makes sense


    //Now some time goes by and we want to update the bound VM w/ new data from the server
    load(serverData);  

    //Problem!
    //this.vm.__ko_mapping__.mappedProperties shows properties for Addresses[0] & Addresses[1]
    //But there is no Addresses[1]!!

    //Lets simulate an update of data (1 more time)
    load(serverData);
    //Interestingly it doesn't get any worse, still just Addresses[0] & Addresses[1]

    function load(d)
    {  
       if (this.vm) //Refresh existing VM
       {
          ko.mapping.fromJS(serverData, vm);
       }
       else    //On 1st Load have mapping create the VM and bind it
       {
          this.vm = ko.mapping.fromJS(serverData);   //Mapping creates object from server data
          ko.applyBindings(this.vm, $("body")[0]);
       }
    }
4

1 回答 1

2

映射插件允许定义一个回调,该回调返回数组中元素的键。(请参阅http://knockoutjs.com/documentation/plugins-mapping.html上的“使用键唯一标识对象” )。这用于确定对象是新的还是旧的。存在三种可能的状态:新对象被添加到数组中,已经存在的元素保留在数组中(但被更新)或现有元素从数组中删除,因为它不再存在于新数据集中。(这些状态实际上由实用函数 ko.utils.compareArrays 确定)

这里正确的状态是“保留”,但由于您没有为数组中的地址提供唯一键,映射插件不知道这些条目实际上是相同的 - 因此状态“删除”被分配给当前对象和状态“添加”到新对象。

这会生成一个包含所有需要注意的元素的列表——当前元素的键为“0”,新的键为“1”,因此“mappedProperties”中有奇怪的条目。我认为这可以被认为是一个错误,但这确实是一个棘手的问题。而且这不是真正的内存泄漏,因为幽灵条目的数量总是numPreviousEntries.

Here is a fiddle demonstrating that the use of unique keys (can be anything if you have not more than one row, so I used the state id) indeed resolves this issue: http://jsfiddle.net/xTHFg/4/

于 2012-04-22T14:45:44.343 回答