我最近在使用 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]);
}
}
最佳答案
映射插件允许定义一个回调,返回数组中元素的键。 (请参阅 http://knockoutjs.com/documentation/plugins-mapping.html 处的“使用键唯一标识对象”)。这用于确定对象是新的还是旧的。存在三种可能的状态:一个新对象被添加到数组中,一个已经存在的元素保留在数组中(但被更新)或者一个现有元素被从数组中删除,因为它不再存在于新数据集中。 (这些状态实际上是由实用函数 ko.utils.compareArrays 确定的)
这里正确的状态是“保留”,但是由于您没有为数组中的地址提供唯一的键,因此映射插件不知道这些条目实际上是相同的 - 因此状态“删除”得到分配给当前对象并将状态“添加”到新对象。
这会产生一个包含所有需要注意的元素的列表 - 当前的元素具有键“0”,新的元素具有键“1”,因此“mappedProperties”中出现奇怪的条目。我认为这可以被认为是一个错误,但它是一个非常棘手的错误。这并不是真正的内存泄漏,因为幽灵条目的数量始终是 numPreviousEntries
。
这里有一个 fiddle ,证明使用唯一键(如果你不超过一行,可以是任何东西,所以我使用了状态 ID)确实解决了这个问题:http://jsfiddle.net/xTHFg/4/
关于knockout.js - Knockout 映射插件或我的代码中存在数组错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10179389/