【问题标题】:Add new item to a list created with the ko.mapping plugin for Knockout.js将新项目添加到使用 Knockout.js 的 ko.mapping 插件创建的列表中
【发布时间】:2012-06-26 23:19:48
【问题描述】:

我正在尝试找出将元素添加到使用 ko.mapping 创建的模型中的列表的规范方法。我created a jsFiddle to tinker

javascript 大致如下:

var mapping, baseModel, view_model;

mapping = {
    outer: [{
        alpha: '',
        beta: [
            {
            carotine: '',
            blockers: ''}
        ]
    }]
};

baseModel = { // add in functionality
    append_outer: function() {
        this.outer.push({});
    },
    append_beta: function(xyz) {
        this.beta.push({});
    }
};

view_model = ko.mapping.fromJS(mapping, {}, baseModel);

ko.applyBindings(view_model, $("#mapped")[0]);​

对应的HTML是on the jsFiddle

当我使用append_outer 时,我希望将一个新元素添加到 view_model 中,该元素与第一个元素基本相同,都带有 observables。当我使用append_beta 时,我希望beta 有一个带有[carotine: ko.observable(), blockers: ko.observable] 的新元素。我还没有看到明显的方法来做到这一点 - 但我希望它是一个非常常见的用例。

由于显而易见的原因,示例代码没有达到我想要的效果!当然,这正是我正在修补的东西,希望能找到一些明显的东西,例如ko.mappingCreate 或类似的。唉,没有这样的运气。

也许提到数据模型是动态的 - 尽管列表中的项目总是具有与其对等项相同的数据表示形式。有人可能会说,用于创建视图模型 (mapping) 的数据是一个原型。

如果有任何想法和方向,我将不胜感激。

【问题讨论】:

    标签: knockout.js knockout-mapping-plugin


    【解决方案1】:

    不是我会这样做...而是为将映射的各个方面作为模板的类型创建一个对象。

    http://jsfiddle.net/keith_nicholas/EEE6J/

    一般来说,我只是用对象定义结构,然后将 json 用于数据。

    【讨论】:

    • 谢谢基思。虽然这当然是一个选项,但我必须根据传递给ko.mapping.fromJS 的相同数据为每种类型创建一个对象(因为它是如前所述的动态创建的)。看来这会重复我原本期望 ko.mapping 固有的功能,我不希望有这样的重复——尽管它可能是必要的。
    • 你在复制什么?映射插件只是通过并将事物变成可观察的。没有它试图在其映射中找出事物的“类型”。它不知道你给它的结构的分解对你很重要。您可以发送一个“模板”结构,这就是我对 MVC 后端所做的事情,然后可以使用它来创建新项目。
    • 虽然它看起来像重复,但它只是其模式形式的数据,看起来与模式非常相似,在你的情况下,你提供的数据没有模式的定义,现在你是想要一个模式,它看起来就像数据:)
    • 嗯,您是否希望“映射”对象成为模式的定义?因为您使用它的方式,它充当数据:)
    • 是的,完全正确 - 我使用空数据的映射作为架构(尽管它实际上可以包含数据 - 作为任何预设默认值)。抱歉,如果不清楚。 :)
    【解决方案2】:

    根据 Keith 的建议,我做了以下事情:

    var mapping, baseModel, view_model;
    
    mapping = {
        outer: [{
            alpha: '',
            beta: [
                {
                carotine: '',
                blockers: '',
                skittles: ''}
            ]}
        ]
    };
    
    baseModel = function(mapping) { // add in functionality
        var self = this;
    
        this._vm_prototype = mapping;
    
        console.log("Prototype: " + ko.mapping.toJSON(this._vm_prototype));
    
        self.append = function(target, proto_getter) {
            console.log("pg: " + proto_getter);
            var prototype = proto_getter(self._vm_prototype);
    
            console.log("Prototype: " + JSON.stringify(prototype));
            console.log("Target: " + ko.mapping.toJSON(target));
    
            this[target].push(ko.mapping.fromJS(prototype));
        };
    };
    
    view_model = ko.mapping.fromJS(mapping, {}, new baseModel(mapping));
    
    ko.applyBindings(view_model, $("#mapped")[0]);​
    

    不幸的是,这需要在 HTML 方面进行一些修改,例如要添加一个新的beta,必须确定它存在于原型中的哪个位置,即

    <button data-bind='click: $root.append.bind($data, "beta", 
            function (proto) { return proto.outer[0].beta[0]; })'>
      Add another beta
    </button>
    

    对于outer

    <button data-bind='click: append.bind($data, "outer", 
            function (proto) { return proto.outer[0]; })'>
     Add another outer
    </button>
    

    append 函数如果只是通过 outer[0].beta[0] 来代替函数,则可以变得更简洁,但随后必须解析或 eval this。

    从 jsFiddle AB 可以看出,唯一改变的是 mapping,但两者的功能都按预期工作。

    再次,我试图避免重复代码,但这很难看。我很想知道如何清理它!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多