【问题标题】:knockoutjs mapping, add new item to child array without the extra mapping objectknockoutjs 映射,在没有额外映射对象的情况下将新项目添加到子数组
【发布时间】:2013-04-16 16:34:03
【问题描述】:

使用这个测试代码,基于我的真实项目:

var test = ko.mapping.fromJS({ id: 1, kids: [{ name: "sue"}] });
test.kids.push({ name: "tim" });
test.kids.push(ko.mapping.fromJS({ name: "joe" }));
console.log(test);
console.log(test.kids()[0]);
console.log(test.kids()[1]);
console.log(test.kids()[2]);
test.kids()[2].__ko_mapping__ = undefined;
console.log(test.kids()[2]);

Firebug 中的控制台输出显示:

Object { __ko-mapping__={...}, id=d(), kids=d() }
Object { name=d() }
Object { name="tim" }
Object { __ko-mapping__={...}, name=d() }
Object { name=d() }

我的目标是在数据的初始映射之后将项目添加到 kids 数组,并使这些项目看起来与添加的原始项目相同。如果我只是将一个对象直接推送到数组上,则属性不是可观察的。如果我使用ko.mapping.fromJS 推送对象,他们会得到一个额外的__ko_mapping__ 对象。我宁愿没有额外的对象,因为它似乎不需要(原始项目没有它并且工作正常),并且我可能会在以后添加 1000 个项目的地方使用相同的设计。

将对象设置为undefined 似乎确实删除了额外的对象,但如果可能的话,宁愿不首先创建它。

【问题讨论】:

  • __ko_mapping__ 在调用ko.mapping.fromJS 时由“根”元素上的映射插件创建和使用。你不应该关心它,它是不可配置的,它是自动添加的。如果您担心内存问题,那么您应该为您的项目创建一个构造函数并使用它而不是映射插件。
  • 我同意上面的评论。 ko_mapping 用于淘汰赛以跟踪添加的内容。当你调用 ko.mapping.toJS() 函数时,那些额外的属性将被删除,当你想将它传递回服务器时,你应该调用它来获取一个干净的对象。另一方面,如果您正在迭代对象的属性并且您担心这可能会导致问题,那么您应该迭代并检查 hasOwnProperty 以确保您正在迭代对象自己的属性。 ko_mapping 将不在其中。
  • 我猜是这样,但似乎很常见,他们会为此提供更优化的方法。我只是在映射一个非常基本的对象,然后想在以后添加一些东西......很遗憾我不得不脱离映射库来做到这一点,或者只是“不用担心”额外的内存(可能是大小的 5 倍)。
  • 如果映射信息一直存在于项目上,我更有可能将其视为“必需”,但对于在初始期间被映射为子项的项目则不存在映射。我想我可以在源代码中找到一个库函数,该函数在每个子节点上被调用以进行初始映射,并直接调用它......但这不是一个好主意。

标签: knockout.js knockout-mapping-plugin


【解决方案1】:

基于缺乏任何其他答案,唯一的答案可能是一个更好的设计实践,但实际上与我要求的相反(它为每个孩子添加了一个映射对象)..我想我已经在我原来的问题中有答案,只是假设必须有更好的方法。

所以对于未来的读者来说,这里是:

test.kids()[2].__ko_mapping__ = undefined;

如果您想摆脱它,只需将 ko_mapping 设置为 undefined。

请参阅 cmets 和其他答案,了解为什么这通常不是一个好主意。对于我的需求,也许你也有同样的需求,这是个好主意。

【讨论】:

    【解决方案2】:

    我通常发现为“Kids”创建一个强大的原型并告诉映射插件在映射您的初始数据时使用它很有用。这将导致数组的内容相同,并具有允许每个 Kid 进行计算和可观察的额外好处。

    http://jsfiddle.net/Z9GF5/

    var Kid = function(json){
        ko.mapping.fromJS(json, {}, this);
    }
    
    var mapping = {
        'kids': {
            create: function(options) {
                return new Kid(options.data);
            }
        }
    }
    

    现在,如果您必须添加项目,只需创建新的孩子。

    var test = ko.mapping.fromJS({ id: 1, kids: [{ name: "sue"}] }, mapping);
    test.kids.push(new Kid({ name: "tim" }));
    test.kids.push(new Kid({ name: "joe" }));
    console.log(test);
    console.log(test.kids()[0]);
    console.log(test.kids()[1]);
    console.log(test.kids()[2]);
    

    Firebug 然后显示:

    Object {id: function, kids: function, __ko_mapping__: Object}
    Kid {name: function, __ko_mapping__: Object}
    Kid {name: function, __ko_mapping__: Object}
    Kid {name: function, __ko_mapping__: Object}
    

    【讨论】:

      【解决方案3】:

      http://knockoutjs.com/documentation/plugins-mapping.html

      您可以选择映射哪些属性以及如何映射。

      【讨论】:

      • 请在答案本身中包含相关部分,而不是仅链接到外部资源。
      猜你喜欢
      • 2014-02-19
      • 2016-09-21
      • 2014-06-06
      • 2014-03-14
      • 2023-03-23
      • 2023-03-08
      • 2018-08-14
      • 2011-10-18
      • 1970-01-01
      相关资源
      最近更新 更多