【问题标题】:Adding properties to the view model created by using the Knockout JS mapping plugin向使用 Knockout JS 映射插件创建的视图模型添加属性
【发布时间】:2012-01-30 05:30:41
【问题描述】:

我正在研究 Knockoutjs 网站上的映射插件示例。

这是示例数据。

Knockout JS Mapping Plugin

var data = {
    name: 'Scott',
    children: [
        { id : 1, name : 'Alice' }
    ]
}

该示例显示了如何覆盖其中一个子对象的映射,但如何更改基础对象的映射。

例如,如果我想向 Scott 添加一个“FavouriteChild”属性,我该怎么做?

我假设我需要在基本映射上使用 create 函数,但我在任何地方都找不到语法示例。

var myChildModel = function(data) {
    ko.mapping.fromJS(data, {}, this);

    this.nameLength = ko.computed(function() {
        return this.name().length;
    }, this);
}

var mapping = {
    'children': {
        create: function(options) {
            return new myChildModel(options.data);
        }
    }
}

var viewModel = ko.mapping.fromJS(data, mapping);

编辑:从下面接受的答案中我发现这是可行的

<span data-bind='text: AdditionalProperty'>

淘汰码

var mapping = {
    create: function (options) {
        //customize at the root level.  
        var innerModel = ko.mapping.fromJS(options.data);

        innerModel.AdditionalProperty = 'Hello World';

        return innerModel;
    }
}

var viewModel = ko.mapping.fromJS(data, mapping);

//use this as our model bindings
ko.applyBindings(viewModel);

【问题讨论】:

    标签: knockout.js


    【解决方案1】:

    您需要在映射对象本身上使用create 方法,例如:

    var mapping = {
      //customize at the root level.  
      create: function(options) {
         //first map the vm like normal
         var vm = ko.mapping.fromJS(options.data);
    
         //now manipulate the returned vm in any way that you like
         vm.someProperty = "test";
    
         vm.someComputed = ko.computed(function() {
              return vm.first() + " " + vm.last();
         });
    
         //return our vm that has been mapped and tweaked
         return vm;
      }
    };
    

    【讨论】:

    • 如何解释如何使用空函数创建并没有展示访问根级别并添加到它。
    • 更新了函数以显示在返回结果之前如何映射和操作结果。
    • 我知道这是一个非常古老的问题,但刚刚遇到它,我想提出一个建议。映射时使用 create 回调的代码示例(在 KnockoutJs 站点上)没有说明 create 方法在映射对象上。 Ryan,如果可以的话,我会要求网站所有者将他们的代码示例替换为上面的代码示例。
    【解决方案2】:

    这是基于 RP Niemeyer 解决方案的此答案的延续

    这里的答案基于上面的解决方案和他的博客——谢谢!我想我应该添加一些细节,因为它解决了数组不是第一级对象的情况。

     var data = {
    person: {
           children: [{ id: 1, firstName: 'Scot', lastName: 'Weise'}]
        }
    };
    
    var mapping = {
        'children': {
            create: function(options) {
                return (new (function() {
                    // setup the computed binding for some reason I had
                    //  to use ko.dependentObservable instead of ko.computed
                    // or errors showed up.
                    this.fullName = ko.dependentObservable(function() {
                        return this.firstName() + ' ' + this.lastName();
                        }, this);
                        ko.mapping.fromJS(options.data, { }, this);
                    })(/* call the ctor here */));
                }
            }
        };
    
        // Create view model and map the data object to the model.
        var viewModel = ko.mapping.fromJS(data, {});
    
        // update the viewModel with the mapping object that contains 
        // some a computed property(s)
        viewModel.person = ko.mapping.fromJS(viewModel.person, mapping);
        ko.applyBindings(viewModel);
    

    请注意,人是第一级对象,孩子是该人的子属性。 viewModel.person = ko.mapping.fromJS(viewModel.person, mapping) 一开始对我来说并不直观。

    这里有一个细微的变化

    person 对象是一个 observable,它是在最初从服务器 json 数据创建之后添加或更新的。

    var viewModel = {};
    $(document).ready(function () {
        var person = getPerson();
    
        // selected person is added to the viewModel
        viewModel.selectedPerson = ko.observable(person);
        ko.applyBindings(viewModel);
    });
    
    function getPerson() { 
    // you would probably pass this into the function as a parameter. 
    var person =
        {
            name: 'jim',
            children: [{ id: 1, firstName: 'jane', lastName: 'bob'}]
        };
    
        var mapping = {
            'children': {
                create: function (options) {
                    return (new (function () {
                        // setup the computed binding
                        this.fullName = ko.dependentObservable(function () {
                        return this.firstName() + ' ' + this.lastName();
                        }, this);
                        ko.mapping.fromJS(options.data, {}, this);
                    })(/* call the ctor here */));
                }
            }
        };
    
        var result = ko.mapping.fromJS(person, mapping);
        return result;
    }
    

    html中的一些绑定代码

    最终,您需要在某些时候使用它,如下所示:

    <div data-bind="foreach:viewModel.selectedPerson().children">
        <span data-bind="text:fullName"></span>
    </div>
    

    感谢您的帮助!没有你的博文,我不可能走到这一步。

    【讨论】:

      【解决方案3】:

      请注意,要在孩子上定义额外的计算 observable,您需要传递另一组映射选项

      var mapping = {
        create: function(options) {
          //customize at the root level.  
      
          var mapping2 = {
            'children': {
              create: function(options) {
                //customize children also
      
              }
            }
          }
      
          //call ko.mapping.fromJS on the options.data as well with further customization
          ko.mapping.fromJS(options.data, mapping2, this);
        }
      };
      

      【讨论】:

      • 我来这里是为了寻找如何映射嵌套属性,恕我直言,这是最清楚的例子。如果它包含 viewModel 的示例,那对我来说将是一个完整的解决方案。
      【解决方案4】:

      另一个基于 Jason 和 RP Niemeyer 提供的示例的示例。

      data 是我们在 ajax 查询之后得到的,我们在其上添加了两个嵌套的 observables(viewModel.weekly.selectedWeekviewModel.monthly.selectedMonth):

          var data = {
              "date": "2017-03-28",
              "weekly": {
                  "weeks": [
                      {
                          "id": "201701",
                          "label": "Week 1"
                      },
                      {
                          "id": "201702",
                          "label": "Week 2"
                      }
                  ]
              },
              "monthly": {
                  "months": [
                      {
                          "id": "201701",
                          "label": "01/2017"
                      },
                      {
                          "id": "201702",
                          "label": "02/2017"
                      }
                  ]
              }
          }
      
          var viewModelMapping = {
              create: function (options) {
                  return (new (function () {
                      // viewModel root level
                      var mapping2 = {
                          'weekly': {
                              create: function (options) {
                                  // viewModel.weekly
                                  return new function () {
                                      var model = ko.mapping.fromJS(options.data, {}, this);
                                      model.selectedWeek = ko.observable();
                                      return model;
                                  };
                              }
                          },
                          'monthly': {
                              create: function (options) {
                                  // viewModel.monthly
                                  return new function () {
                                      var model = ko.mapping.fromJS(options.data, {}, this);
                                      model.selectedMonth = ko.observable();
                                      return model;
                                  };
                              }
                          }
                      };
      
                      ko.mapping.fromJS(options.data, mapping2, this);
                  })());
              }
          };
      
      
          var viewModel = ko.mapping.fromJS(data, viewModelMapping);
          ko.applyBindings(viewModel);
      

      【讨论】:

        猜你喜欢
        • 2017-06-25
        • 1970-01-01
        • 2015-04-22
        • 2012-12-26
        • 2015-03-17
        • 2012-09-25
        • 1970-01-01
        • 2012-02-08
        • 2013-06-08
        相关资源
        最近更新 更多