【问题标题】:Knockout Mapping - Fill Observable Arrays keeping Items' methodsKnockout Mapping - 填充 Observable 数组以保持项目的方法
【发布时间】:2012-08-03 11:22:30
【问题描述】:

我一直面临的问题基本上如下:

  • 我有一个淘汰视图模型,其中包含具有可观察属性和方法的可观察项目数组。
  • 我需要从服务器中提取数据。从服务器获取数据后,方法需要存在。所以我创建了一个新的 ViewModel,然后根据来自服务器的内容更新它的值。 (这不起作用,生成的数组没有项目)
  • 如果我使用mapping 创建一个使用var newObj = ko.mapping.fromJS(data) 的新对象,则生成的数组有项目,但它的项目没有方法。它破坏了我的绑定。

我的问题的小提琴:http://jsfiddle.net/claykaboom/R823a/3/(它在你点击“从服务器加载数据”中起作用)

最后一个问题是:在不使加载过程过于繁琐的情况下,将项目放在最终数组中的最佳方法是什么,例如遍历每个项目并填充项目的属性以保留先前声明的方法?

谢谢,

【问题讨论】:

    标签: ajax knockout.js knockout-mapping-plugin ko.observablearray


    【解决方案1】:

    我稍微更改了您的代码。检查此版本的JSFiddle

     var jsonFromServer = '{"ModuleId":1,"Metadatas":[{"Id":1,"MinValue":null,"MaxValue":null,"FieldName":"Teste","SelectedType":"String","SelectedOptionType":null,"IsRequired":true,"Options":[]}]}';
    

    您的代码不起作用,因为您的 jsonFromServer 变量不包含我们在绑定时需要的方法,就像您在问题中描述的那样。 (--> 元数据)

    所以我们需要在映射过程中为 Metadata 对象定义一个自定义创建函数,如下所示:

    var mapping = {
        'Metadatas': {
            create: function(options) {
                var newMetaData = new MetadataViewModel(options.parent);
    
                newMetaData.Id(options.data.id);
                newMetaData.FieldName(options.data.FieldName);
                newMetaData.SelectedType(options.data.SelectedType);
                newMetaData.SelectedOptionType(options.data.SelectedOptionType);
                newMetaData.IsRequired(options.data.IsRequired);
                newMetaData.Options(options.data.Options);
    
                // You can get current viewModel instance via options.parent
                // console.log(options.parent);
    
                return newMetaData;
            }
        }
    }
    

    然后我将您的加载功能更改为:

    self.LoadDataFromServer = function() {
    
        var jsonFromServer = '{"ModuleId":1,"Metadatas":[{"Id":1,"MinValue":null,"MaxValue":null,"FieldName":"Teste","SelectedType":"String","SelectedOptionType":null,"IsRequired":true,"Options":[]}]}';
    
        ko.mapping.fromJSON(jsonFromServer, mapping, self);
    }
    

    您不必声明新的 viewModel 并再次调用 ko.applyBindings。将更新后的映射分配给当前 viewModel 就足够了。欲了解更多信息,请查看this link。注意自定义对象构造部分。

    最后一个问题是:在决赛中放置物品的最佳方式是什么 数组而不会使加载过程过于繁琐,例如 遍历每个项目并填充项目的属性,以便 保留之前声明的方法?

    据我所知,没有简单的方法可以通过您的对象实现来做到这一点。你的对象并不简单。它们同时包含数据和函数。因此,您需要为它们定义自定义创建功能。但是,如果您可以像下面这样将其分开,那么您不必自定义对象构造。

    例如将 MetadataViewModel 分成两个不同的对象:

     --> Metadata  : which contains only simple data
     --> MetadataViewModel : which contains Metadata observableArray and its Metadata manipulator functions
    

    使用此结构,您可以调用 ko.mapping.fromJSON(newMetaDataArray , {} , MetadataViewModelInstance.MetadataArray) 而无需在映射过程中定义自定义创建函数。

    【讨论】:

    • 好吧!这是一个非常完整的答案!我很感激。它就像一个魅力。然而,由于模型的复杂性,我们最终将每个属性从服务器传递到客户端。这意味着添加新属性代表代码更改,这更有可能导致更多错误。
    猜你喜欢
    • 2013-04-22
    • 2012-07-19
    • 2013-03-14
    • 2013-01-09
    • 2017-03-29
    • 1970-01-01
    • 1970-01-01
    • 2013-08-08
    • 2013-11-10
    相关资源
    最近更新 更多