【问题标题】:Knockout mapping - Uniquely identifying nested objects using keys敲除映射 - 使用键唯一标识嵌套对象
【发布时间】:2012-08-14 03:38:04
【问题描述】:

The Knockout mapping plugin documentation 有一节题为“使用“键”唯一标识对象”。这描述了如何更新对象的一部分,然后仅更新显示的该部分,而不是完全替换部分修改对象的所有属性的显示。在他们的简单示例中,这一切都非常出色,我在这里对其进行了轻微修改,以使我的问题更清楚。我的修改是:

  1. 延迟 2 秒后用更正名称替换对象。

  2. 突出显示显示中不变的部分,这样你就可以看到更新发生时它实际上并没有被替换。

1.简单对象 (jsFiddle)

<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>

但我不清楚如何为更复杂的嵌套数据结构实现相同的行为。在下面的示例中,我采用了上面的代码并将数据包装在一个列表中。我希望它的行为与上述相同,但事实并非如此。由于一个属性的变化,整个显示被重做。您可以看到这一点,因为与上面的示例不同,数据更新后突出显示会丢失。

2。更复杂的嵌套对象 (jsFiddle)

<!-- 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>

所以基本上我要问的是,考虑到更多嵌套的数据结构,我怎样才能使第二个示例像第一个示例一样工作?您可以假设每个孩子的 id 都是唯一的(因此,如果我在 Scott 之外添加另一个父母,他的孩子将以 id=2 开头,等等)。

【问题讨论】:

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


    【解决方案1】:

    那里的观察很有趣,写得很好。如果您在父级和子级上定义一个键,它似乎可以工作。试试这个小提琴:

    http://jsfiddle.net/8QJe7/6/

    它为父级和子级定义了可实例化的视图模型函数,父构造函数在其中进行子映射。

    【讨论】:

    • 谢谢,这似乎可行,虽然我希望有一种更简单、更直观的方法,因为必须为父母和孩子定义密钥似乎很奇怪,即使它只用于孩子——知道为什么吗?另外,您知道多次调用 ko.mapping.fromJS 是否会显着降低性能?我想这可能取决于上下文,这样做是否有意义或天真地更新所有内容?
    • 我还没有深入研究映射插件的内部结构,但我认为它需要能够识别孩子的父母是有充分理由的,因为它通过对象和 DOM 元素的层次结构工作。重新性能 - 我的视图模型层次结构大约有 6 级深,全部实现为可实例化的函数,这些函数使用我的小提琴中的键创建它们的子级。每个级别的兄弟姐妹的数量变化很大,但它在我的应用程序的实际使用参数内从上到下进行映射更新时执行非常顺利。每个应用都会有所不同。
    • 由于各种复杂的原因,我实际上确实开始了自己的映射过程 - 但最终我放弃并重新考虑了我的应用程序逻辑,转而使用映射插件。我发现通过唯一键对嵌套对象和数组进行大规模稳健更新并不是一件容易的事,而且我认为他们在使用该插件方面做得很好。
    猜你喜欢
    • 1970-01-01
    • 2012-12-14
    • 1970-01-01
    • 2014-12-30
    • 2016-10-14
    • 1970-01-01
    • 1970-01-01
    • 2020-09-27
    • 2013-08-01
    相关资源
    最近更新 更多