我试图基于此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);
但没有成功,有没有办法实现?
答案 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>