KnockoutJS映射插件(observableArray)(KnockoutJS Mapping

2019-10-22 19:15发布

我是新来的美人,我有使用映射插件,因为我不明白它是如何映射我的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数据包含手机的数组。
我用淘汰赛映射插件,我可以绑定“名”,“邮件”和环形的电话号码:直到我试图让在phoneNumber的一个ko.compute这是一个对象,在没有麻烦“的foreach手机”阵列手机。

@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

我试图通过地方phoneNumber的在我这样的结合使用reformatPhoneNumber做到这一点:

<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。
任何帮助将不胜感激。 非常感谢你!!

Answer 1:

您使用的命名(一个名为计算的reformatPhoneNumber )建议,你认为computeds的功能。 虽然他们在技术上,功能,其代表的值。 把他们当作价值,就像你对待观测。 在你的情况,这意味着它应该被称为更像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);
        }
    }
};

现在,您可以通过实例化一个电话簿对象创建整个对象图:

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

通读映射插件的文档 。

展开下面的代码片段,看看它的工作。

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



文章来源: KnockoutJS Mapping Plugin (observableArray)