使用淘汰表

时间:2018-10-22 08:40:07

标签: knockout.js

我试图基于此article在剔除中创建对象内部属性。可以像这样自定义对象:

var data = {
        name: 'Graham',
        children: [
            { id : 1, name : 'Lisa' }
        ]
}

然后为其创建地图:

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

具有要添加为新myChildModel()的自定义字段,如下所示:

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

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

但是如果我要自定义的数据位于对象的内部属性中怎么办

var data = {
            name: 'Graham',
            family :{

    parents: [
                { id : 1, name : 'Duke' }
              ],

    children: [
                { id : 1, name : 'Lisa' }
              ]
        }
    }

在这里,我想自定义位于家庭对象内部的子数组,该数组也位于数据对象内部。

这是我尝试过的:

var mapping = {
    'family.children': {
        create: function(options) {
            return new myChildModel(options.data);
        }
    }
}
var viewModel = ko.mapping.fromJS(data, mapping);

还有:

var mapping = {
    'family[children]': {
        create: function(options) {
            return new myChildModel(options.data);
        }
    }
}
var viewModel = ko.mapping.fromJS(data, mapping);

但没有成功,有没有办法实现?

1 个答案:

答案 0 :(得分:0)

您可以通过为create属性指定一个family函数来嵌套映射,在其中引用children策略。

var personData = {
  name: 'Graham',
  family: {
    parents: [{
      id: 1,
      name: 'Duke'
    }],

    children: [{
      id: 1,
      name: 'Lisa'
    }]
  }
}

var familyMapping = {
  'children': {
    create: function(childData) {
      return new MyChildModel(childData.data);
    }
  }
}

var personMapping = {
  'family': {
    create: function(familyData) {
      return ko.mapping.fromJS(familyData.data, familyMapping, {});
    }
  }
}

var person = ko.mapping.fromJS(personData, personMapping);
ko.applyBindings(person);

function MyChildModel(data) {
  ko.mapping.fromJS(data, {}, this);

  this.nameLength = ko.computed(function() {
    return this.name().length;
  }, this);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.min.js"></script>

<ul data-bind="foreach: family.children">
  <li>
    <input data-bind="textInput: name"> (<span data-bind="text: nameLength"></span>)
  </li>
</ul>

我不得不说我不是地图插件的忠实粉丝。我认为这并不比编写自己的构造函数更好,这不是很多工作。

function Person(id, name, parentsData, childrenData) {
  // For one way binding
  this.id = id;
  
  // For two way binding
  this.name = ko.observable(name);
  
  this.parents = ko.observableArray(
    parentsData.map(Person.fromData)
  );
  
  this.children = ko.observableArray(
    childrenData.map(Person.fromData)
  );

  // Computed
  this.nameLength = ko.pureComputed(
    function() { return this.name().length; },
    this
  );
}

Person.fromData = function(apiData) {
  const id = apiData.id || null;
  const name = apiData.name || "Unknown";
  const parentsData = apiData.family 
    ? apiData.family.parents
    : [];
  const childrenData = apiData.family
    ? apiData.family.children
    : [];
  
  return new Person(id, name, parentsData, childrenData);
}

var personData = {
  name: 'Graham',
  family: {
    parents: [{
      id: 1,
      name: 'Duke'
    }],

    children: [{
      id: 1,
      name: 'Lisa'
    }]
  }
}

ko.applyBindings(Person.fromData(personData));
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.min.js"></script>

<div data-bind="template: { data: [$data], name: 't-personList' }"></div>

<script type="text/html" id="t-personList">
  <ul data-bind="foreach: $data">
    <li>
      <input data-bind="textInput: name">(<span data-bind="text: nameLength"></span>)
      <!-- ko if: parents().length -->
      <h3>Parents</h3>
      <div data-bind="template: { data: parents, name: 't-personList' }"</div>
      <!-- /ko -->
      <!-- ko if: children().length -->
      <h3>Children</h3>
      <div data-bind="template: { data: children, name: 't-personList' }"</div>
      <!-- /ko -->
    </li>
  </ul>
</script>