1

根据这篇文章,我正在尝试在淘汰赛中创建一个对象内部属性。可以像这样自定义对象:

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);

使用您要添加为 new 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);

但没有一个工作,有没有办法可以实现?

4

1 回答 1

0

您可以通过为引用策略的属性指定一个create函数来嵌套映射。familychildren

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>

于 2018-10-22T09:55:21.137 回答