【问题标题】:Knockout.js mapping JSON object to Javascript ObjectKnockout.js 将 JSON 对象映射到 Javascript 对象
【发布时间】:2012-02-06 23:58:23
【问题描述】:

我在将从服务器接收到的 Json 对象映射到预定义的 Javascript 对象时遇到问题,该对象包含绑定中使用的所有必要函数

Javascript代码如下

function Person(FirstName, LastName, Friends) {
    var self = this;
    self.FirstName = ko.observable(FirstName);
    self.LastName = ko.observable(LastName);
    self.FullName = ko.computed(function () {
        return self.FirstName() + ' ' + self.LastName();
    })
    self.Friends = ko.observableArray(Friends);
    self.AddFriend = function () {
        self.Friends.push(new Person('new', 'friend'));
    };
    self.DeleteFriend = function (friend) {
        self.Friends.remove(friend);
    };      
}

var viewModel = new Person();

$(document).ready(function () {
    $.ajax({
        url: 'Home/GetPerson',
        dataType: 'json',
        type: 'GET',
        success: function (jsonResult) {
            viewModel = ko.mapping.fromJS(jsonResult);
            ko.applyBindings(viewModel);
        }
    });
});

HTML:

<p>First name: <input data-bind="value: FirstName" /></p>
<p>Last name: <input data-bind="value: LastName" /></p>
<p>Full name: <span data-bind="text: FullName" /></p>
<p>#Friends: <span data-bind="text: Friends().length" /></p>
@*Allow maximum of 5 friends*@
<p><button data-bind="click: AddFriend, text:'add new friend', enable:Friends().length < 5" /></p>
<br>
@*define how friends should be rendered*@
<table data-bind="foreach: Friends">
    <tr>
        <td>First name: <input data-bind="value: FirstName" /></td>
        <td>Last name: <input data-bind="value: LastName" /></td>
        <td>Full name: <span data-bind="text: FullName" /></td> 
        <td><button data-bind="click: function(){ $parent.DeleteFriend($data) }, text:'delete'"/></td> 
    </tr>
</table>

用于获取初始数据的 ServerSide MVC 代码如下所示:

    public ActionResult GetPerson()
    {
         Person person = new Person{FirstName = "My", LastName="Name",
                        Friends = new List<Person>
                        {
                             new Person{FirstName = "Friend", LastName="Number1"},
                             new Person{FirstName = "Friend", LastName="Number2"}
                        }
        };
        return Json(person, JsonRequestBehavior.AllowGet);
    }

我正在尝试使用映射插件将 Json 加载到我的 Javascript 对象中,以便所有内容都可用于绑定(添加函数和 Friend 对象上的计算属性)。

当我使用映射插件时,它似乎不起作用。 使用插件时,AddFriend 方法在绑定期间不可用。 是否可以使用映射插件填充 JavaScript Person 对象,还是必须手动完成所有操作?

【问题讨论】:

    标签: knockout.js knockout-mapping-plugin


    【解决方案1】:

    您可以查看将映射选项传递给映射插件,特别是 create 回调,如 here 所述。

    类似:

    var mapping = {
        create: function(options) {
            var person = options.data,
                friends = ko.utils.arrayMap(person.Friends, function(friend) {
                   return new Person(friend.FirstName, friend.LastName);   
                });
    
            return new Person(person.FirstName, person.LastName, friends);
        }
    };
    

    示例:http://jsfiddle.net/rniemeyer/5EWDG/

    但是,在这种情况下,您不会从映射插件中获得很多功能,您可以在不自己调用 Person 构造函数并将 Friends 数组映射到构造函数中的 Person 对象的情况下做到这一点,例如: http://jsfiddle.net/rniemeyer/mewZD/

    您的 HTML 中的另一条注释:确保对于包含内容的元素,您指定了开始和结束标记(spanbutton 在您的代码中不是这种方式)。如果你没有正确指定它们,KO会出现问题。

    【讨论】:

    • 非常感谢!您的回答非常清楚地说明了映射的工作原理。
    • Ryan,一旦你开始构建自己的构造函数,我一直想知道映射插件的实用性(比如你的“你没有从映射插件中获得很多权力”评论)。当我开始使用构造函数时,我是否走错了路?如果我不使用构造函数,我不知道如何最好地处理将映射数据附加到用户输入的数据。使用构造函数,我可以处理用户输入、检查错误、安全性等。我刚刚开始淘汰并希望走正确的路。想法?
    • 如果你想要最好的控制,那么我觉得用构造函数自己做是最好的方法。映射插件的create 回调确实可以让您在各个级别添加自己的属性,但对我来说从来没有这么干净。当您只想将结构转换为可观察对象而不编写太多真正的客户端代码时,映射插件非常有用。
    • 仅供参考,我刚刚发现淘汰赛教程还建议手动映射到您自己的对象以获得更多控制(请参阅第 2 步):learn.knockoutjs.com/#/?tutorial=loadingsaving
    猜你喜欢
    • 2019-05-27
    • 2014-11-07
    • 2012-04-23
    • 2017-12-24
    • 1970-01-01
    • 2013-04-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多