KnockoutJS映射插件(observableArray) [英] KnockoutJS Mapping Plugin (observableArray)

查看:76
本文介绍了KnockoutJS映射插件(observableArray)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是淘汰赛的新手,但使用映射插件时遇到问题,因为我不了解它如何映射我的JSON数据.
这是一个示例json数据,类似于我程序中的数据:

I am new to knockout and I am having a problem with using the mapping plugin as I do not understand how it maps my JSON data.
This is a sample json data similar to what is in my program:

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为止,这是该对象中的一个对象.阵列电话.

As you can see, this json data contains an array of phones.
I used knockout mapping plugin and I can bind the 'name', 'email' and loop the phone numbers in a 'foreach: phones' with no hassle until I try to make a ko.compute on the phoneNumber which is an object in the array phones.

@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

This is 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;
    });

    };

对于视觉表示,这是现在的样子:

For visual representation this is how this looks right now:

Name: John
Email: address@domain.com
Phones:
<--foreach: phones -->
Home Phone: 999-888-777
Business Phone: 444-888-777

我想做的是重新格式化phoneNumber以便以这种方式显示它:

What Im trying to do is to reformat the phoneNumber to display it this way:

Name: John
Email: address@domain.com
Phones:
<--foreach: phones -->
Home Phone: (+1)999-888-777
Business Phone: (+1)444-888-777

我尝试通过使用repatatPhoneNumber代替我的绑定中的phoneNumber来做到这一点:

I try to do it by using the reformatPhoneNumber in place of phoneNumber in my binding like this:

<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的新手.
任何帮助将不胜感激.非常感谢!!

But when I do, the value of reformatPhoneNumber doesn't appear. I read somewhere here that I have to make the objects inside my observableArray also observable because ko.mapping doesn't do that by default. But I cannot picture how to do it as I was expecting ko.mapping plugin to do all the job automatically for me as I am new to this jslibrary.
Any help would be greatly appreciated. Thank you very much!!

推荐答案

您对命名的使用(一个名为reformatPhoneNumber的计算值)表明您将计算值视为函数.从技术上讲,它们是功能,它们表示值.将它们视为价值,就像对待可观察物一样.就您而言,这意味着应该更像formattedPhoneNumber来调用它,并且应将其作为电话号码的属性而不是联系人的属性.

Your use of naming (a computed named reformatPhoneNumber) suggests that you think of computeds as functions. While they are, technically, functions, they represent values. Treat them as values, just like you treat observables. In your case this means it should be called more like formattedPhoneNumber and should live as a property of the phone number, not as a property of the contact.

将模型分成可以从原始数据进行自我引导的单个单元.

Separate your models into individual units that can bootstrap themselves from raw data.

模型层次结构中最小的信息单元是电话号码:

The smallest unit of information in your model hierarchy is a phone number:

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 = {};

层次结构中的下一个是联系人.它包含电话号码.

Next in the hierarchy is a contact. It contains phone numbers.

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

下一个是联系人列表(或电话簿),其中包含联系人:

Next is a contact list (or phone book), it contains contacts:

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对象来创建整个对象图:

Now you can create the entire object graph by instantiating a PhoneBook object:

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

通读映射插件的文档.

展开以下代码段以查看其工作原理.

Expand the following code snippet to see it work.

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映射插件(observableArray)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆