我是淘汰赛的新手,我在使用映射插件时遇到问题,因为我不明白它是如何映射我的JSON数据的。
这是一个类似于我程序中的示例json数据:
contact: {
name : 'John',
email : 'address@domain.com',
phones : [{
phoneType : 'Home Phone',
phoneNumber: '999-888-777'},
{
phoneType : 'Business Phone',
phoneNumber: '444-888-777'},
}]
}
如您所见,此json数据包含一系列手机。
我使用了淘汰映射插件,我可以绑定'名称','电子邮件'并在'foreach:phones'中循环电话号码,没有麻烦,直到我尝试在phoneNumber上创建一个ko.compute,这是一个对象。阵列电话。
@section scripts
{
<script src="~/ViewModels/ContactModel.js"></script>
<script type="text/javascript">
var viewModel = new ContactModel(@Html.Raw(Model.ToJson()));
$(document).ready(function () {
ko.applyBindings(viewModel);
});
</script>
<label>Name</label><input data-bind="value: name" />
<label>Email</label><input data-bind="value: email" />
<label>Phones</label>
<table>
<tbody data-bind="foreach: phones">
<tr>
<td><strong data-bind='text: phoneType'></strong></td>
<td><input data-bind='value: phoneNumber' /></td>
</tr>
/tbody>
</table>
这是ContactModel.js
var ContactModel = function (data) {
var self = this;
ko.mapping.fromJS(data, {}, self);
self.reformatPhoneNumber = ko.computed(function(){
var newnumber;
newnumber = '+(1)' + self.phones().phoneNumber;
return newnumber;
});
};
对于直观表示,这就是现在的看法:
Name: John
Email: address@domain.com
Phones:
<--foreach: phones -->
Home Phone: 999-888-777
Business Phone: 444-888-777
我想要做的是重新格式化phoneNumber以这种方式显示它:
Name: John
Email: address@domain.com
Phones:
<--foreach: phones -->
Home Phone: (+1)999-888-777
Business Phone: (+1)444-888-777
我试着通过在我的绑定中使用reformatPhoneNumber代替phoneNumber来做到这一点:
<table>
<tbody data-bind="foreach: phones">
<tr>
<td><strong data-bind='text: phoneType'></strong></td>
<td><input data-bind='value: $root.reformatPhoneNumber' /></td>
</tr>
/tbody>
</table>
但是当我这样做时,reformatPhoneNumber的值不会出现。
我在这里读到的地方,我必须使我的observableArray中的对象也是可观察的,因为默认情况下ko.mapping不会这样做。但我无法想象如何做到这一点,因为我期待ko.mapping插件自动完成所有工作,因为我是这个jslibrary的新手。
任何帮助将不胜感激。非常感谢!!
答案 0 :(得分:4)
您对命名的使用(计算名为reformatPhoneNumber
)表明您将计算机视为函数。虽然它们在技术上是功能,但它们代表值。将它们视为价值观,就像对待可观察者一样。在您的情况下,这意味着它应该更像formattedPhoneNumber
,并且应该作为电话号码的属性,而不是联系人的财产。
将您的模型分成可以从原始数据引导自己的单个单元。
模型层次结构中最小的信息单位是电话号码:
function PhoneNumber(data) {
var self = this;
self.phoneType = ko.observable();
self.phoneNumber = ko.observable();
self.formattedPhoneNumber = ko.pureComputed(function () {
return '+(1) ' + ko.unwrap(self.phoneNumber);
});
ko.mapping.fromJS(data, PhoneNumber.mapping, self);
}
PhoneNumber.mapping = {};
层次结构中的下一个是联系人。它包含电话号码。
function Contact(data) {
var self = this;
self.name = ko.observable();
self.email = ko.observable();
self.phones = ko.observableArray();
ko.mapping.fromJS(data, Contact.mapping, self);
}
Contact.mapping = {
phones: {
create: function (options) {
return new PhoneNumber(options.data);
}
}
};
接下来是联系人列表(或电话簿),它包含联系人:
function PhoneBook(data) {
var self = this;
self.contacts = ko.observableArray();
ko.mapping.fromJS(data, PhoneBook.mapping, self);
}
PhoneBook.mapping = {
contacts: {
create: function (options) {
return new Contact(options.data);
}
}
};
现在,您可以通过实例化PhoneBook对象来创建整个对象图:
var phoneBookData = {
contacts: [{
name: 'John',
email: 'address@domain.com',
phones: [{
phoneType: 'Home Phone',
phoneNumber: '999-888-777'
}, {
phoneType: 'Business Phone',
phoneNumber: '444-888-777'
}]
}]
};
var phoneBook = new PhoneBook(phoneBookData);
通读documentation of the mapping plugin。
展开以下代码段以查看其是否有效。
function PhoneBook(data) {
var self = this;
self.contacts = ko.observableArray();
ko.mapping.fromJS(data, PhoneBook.mapping, self);
}
PhoneBook.mapping = {
contacts: {
create: function (options) {
return new Contact(options.data);
}
}
};
// ------------------------------------------------------------------
function Contact(data) {
var self = this;
self.name = ko.observable();
self.email = ko.observable();
self.phones = ko.observableArray();
ko.mapping.fromJS(data, Contact.mapping, self);
}
Contact.mapping = {
phones: {
create: function (options) {
return new PhoneNumber(options.data);
}
}
};
// ------------------------------------------------------------------
function PhoneNumber(data) {
var self = this;
self.phoneType = ko.observable();
self.phoneNumber = ko.observable();
self.formattedPhoneNumber = ko.pureComputed(function () {
return '+(1) ' + ko.unwrap(self.phoneNumber);
});
ko.mapping.fromJS(data, PhoneNumber.mapping, self);
}
PhoneNumber.mapping = {};
// ------------------------------------------------------------------
var phoneBook = new PhoneBook({
contacts: [{
name: 'John',
email: 'address@domain.com',
phones: [{
phoneType: 'Home Phone',
phoneNumber: '999-888-777'
}, {
phoneType: 'Business Phone',
phoneNumber: '444-888-777'
}]
}]
});
ko.applyBindings(phoneBook);
&#13;
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout/3.3.0/knockout-min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.js"></script>
<ul data-bind="foreach: contacts">
<li>
<div data-bind="text: name"></div>
<div data-bind="text: email"></div>
<ul data-bind="foreach: phones">
<li>
<span data-bind="text: phoneType"></span>:
<span data-bind="text: formattedPhoneNumber"></span>
</li>
</ul>
</li>
</ul>
<hr />
Model data:
<pre data-bind="text: ko.toJSON(ko.mapping.toJS($root), null, 2)"></pre>
Viewmodel data:
<pre data-bind="text: ko.toJSON($root, null, 2)"></pre>
&#13;