Javascript 敲除映射-使用键唯一标识嵌套对象
有一节题为“使用“键”唯一标识对象”。这描述了如何更新对象的一部分,然后仅更新该部分显示,而不是完全替换部分修改对象的所有属性的显示。在他们的简单示例中,所有这些都非常出色,我在这里稍微修改了一下,以使我的问题更加清楚。我的修改是:Javascript 敲除映射-使用键唯一标识嵌套对象,javascript,knockout.js,knockout-mapping-plugin,Javascript,Knockout.js,Knockout Mapping Plugin,有一节题为“使用“键”唯一标识对象”。这描述了如何更新对象的一部分,然后仅更新该部分显示,而不是完全替换部分修改对象的所有属性的显示。在他们的简单示例中,所有这些都非常出色,我在这里稍微修改了一下,以使我的问题更加清楚。我的修改是: 延迟2秒后,用正确的名称替换对象 高亮显示显示的不变部分,以便在更新时可以看到它实际上没有被替换 1。简单对象() 风险值数据={ 姓名:'斯科特', 儿童:[ {id:1,名称:'Alicw'} ] }; 变量映射={ 儿童:{ 键:功能(数据){ 控制台
风险值数据={
姓名:'斯科特',
儿童:[
{id:1,名称:'Alicw'}
]
};
变量映射={
儿童:{
键:功能(数据){
控制台日志(数据);
返回ko.utils.unwrapobbservable(data.id);
}
}
};
var viewModel=ko.mapping.fromJS(数据,映射);
应用绑定(视图模型);
var range=document.createRange();
range.selectNode(document.getElementsByClassName(“id”)[0]);
window.getSelection().addRange(范围);
setTimeout(函数(){
风险值数据={
姓名:'斯科特',
儿童:[
{id:1,名称:'Alice'}
]
};
fromJS(数据,视图模型);
}, 2000);
但我不清楚的是,对于更复杂的嵌套数据结构,如何实现相同的行为。在下面的示例中,我使用上面的代码并将数据包装在一个列表中。我希望它的行为与上面的一样,但事实并非如此。由于一个属性中的更改,整个显示将重新进行。您可以看到这一点,因为与上面的示例不同,高亮显示在数据更新后丢失
2。更复杂的嵌套对象()
风险值数据={
家长:[
{
姓名:'斯科特',
儿童:[
{id:1,名称:'Alicw'}
]
}
]
};
变量映射={
儿童:{
键:功能(数据){
控制台日志(数据);
返回ko.utils.unwrapobbservable(data.id);
}
}
};
var viewModel=ko.mapping.fromJS(数据,映射);
应用绑定(视图模型);
var range=document.createRange();
range.selectNode(document.getElementsByClassName(“id”)[0]);
window.getSelection().addRange(范围);
setTimeout(函数(){
风险值数据={
家长:[
{
姓名:'斯科特',
儿童:[
{id:1,名称:'Alice'}
]
}
]
};
fromJS(数据,视图模型);
}, 2000);
所以基本上我要问的是,如果数据结构更加嵌套,如何使第二个示例像第一个一样工作?您可以假设每个孩子的id都是唯一的(因此,如果我添加了除Scott之外的另一位家长,他的孩子将以id=2开始,等等)。这里有有趣的观察和精彩的报道。如果在父项和子项上定义键,则该选项似乎有效。试试这把小提琴:
它为父级和子级定义了可实例化的视图模型函数,父级构造函数在其中进行子级映射。谢谢,这似乎确实可行,尽管我希望有一种更简单、更直观的方法,因为它似乎很奇怪,必须为父母和孩子定义密钥,即使它只用于孩子-知道为什么吗?另外,您知道多次调用ko.mapping.fromJS是否会对性能造成严重影响吗?我想这可能取决于上下文,无论是这样做还是天真地更新所有内容都是有意义的?我还没有深入研究映射插件的内部,但我认为有一个很好的理由说明为什么它需要能够在对象和DOM元素的层次结构中识别子对象的父对象。重新性能-我的视图模型层次结构大约有6层,都是作为可实例化函数实现的,这些函数使用键创建它们的子对象,就像我的小提琴一样。每个级别上的同级数量变化很大,但在我的应用程序的实际使用参数范围内,从上到下进行映射更新时,它执行得非常顺利。每个应用程序都会有所不同。实际上,出于各种复杂的原因,我开始做自己的映射过程——但最终我放弃了,重新思考了我的应用程序逻辑,转而使用映射插件。我发现用唯一的键对嵌套对象和数组进行大规模健壮的更新不是一件小事,我认为他们在插件方面做得相当不错。
<h1 data-bind="text: name"></h1>
<ul data-bind="foreach: children">
<li><span class="id" data-bind="text: id"></span> <span data-bind="text: name"></span></li>
</ul>
<script>
var data = {
name: 'Scot',
children: [
{id : 1, name : 'Alicw'}
]
};
var mapping = {
children: {
key: function(data) {
console.log(data);
return ko.utils.unwrapObservable(data.id);
}
}
};
var viewModel = ko.mapping.fromJS(data, mapping);
ko.applyBindings(viewModel);
var range = document.createRange();
range.selectNode(document.getElementsByClassName("id")[0]);
window.getSelection().addRange(range);
setTimeout(function () {
var data = {
name: 'Scott',
children: [
{id : 1, name : 'Alice'}
]
};
ko.mapping.fromJS(data, viewModel);
}, 2000);
</script>
<!-- ko foreach: parents -->
<h1 data-bind="text: name"></h1>
<ul data-bind="foreach: children">
<li><span class="id" data-bind="text: id"></span> <span data-bind="text: name"></span></li>
</ul>
<!-- /ko -->
<script>
var data = {
parents: [
{
name: 'Scot',
children: [
{id : 1, name : 'Alicw'}
]
}
]
};
var mapping = {
children: {
key: function(data) {
console.log(data);
return ko.utils.unwrapObservable(data.id);
}
}
};
var viewModel = ko.mapping.fromJS(data, mapping);
ko.applyBindings(viewModel);
var range = document.createRange();
range.selectNode(document.getElementsByClassName("id")[0]);
window.getSelection().addRange(range);
setTimeout(function () {
var data = {
parents: [
{
name: 'Scott',
children: [
{id : 1, name : 'Alice'}
]
}
]
};
ko.mapping.fromJS(data, viewModel);
}, 2000);
</script>