我是knockout.js的新手,我试图绑定到表示用户的以下对象:
{ "$id": "1","$values": [ { "$id": "2","Locations": { "$id": "3","$values": [] },"Photos": { "$id": "4","UserId": 1,"Name": "Test User" } ] }
用户可以零个或多个位置,以及零个或多个照片.
视图模式:
function Usersviewmodel() { var self = this; self.users = ko.observableArray(); var baseUri = 'http://localhost:46241/api/users'; $.getJSON(baseUri,function (data) { self.users = data; }); } $(document).ready(function () { ko.applyBindings(new Usersviewmodel()); })
HTML包含以下绑定:
<ul id="update-users" data-bind="foreach: users"> <li> <div><div class="item">User ID</div> <input type="text" data-bind="value: $data.UserId" /> </div> <div><div class="item">Name</div> <input type="text" data-bind="value: $data.Name" /> </div> </li> </ul>
我这样做不对吗?还是用户的对象引用位置和照片可能会搞乱绑定?
解决方法
Am I flat out doing this incorrectly?
是.您将在JSON回调中覆盖observableArray,从而破坏它:
$.getJSON(baseUri,function (data) { self.users = data; });
一般来说,淘汰可观测量分配如下:
$.getJSON(baseUri,function (data) { self.users(data.$values); });
请注意,在您的情况下,数据.$值似乎包含实际数组,而不是数据本身.
这将适用于您的情况,但它并没有使用敲除它的全部潜力.
mapping plugin是为这种情况创建的.它递归地遍历一个复杂的对象,并将其所有的属性变成可观察的,并将所有的数组都包含到可观察的数组中.这样可以对对象的状态进行细粒度的控制,从而可以监视每个变化.
$.getJSON(baseUri,function (data) { ko.mapping.fromJS(data.$values,{},self.users); });
它还允许部分更新:假设您从服务器检索用户列表,并且您的视图模型已经有一半.映射插件只能添加缺省的视图模型,并对现有模型进行适当的更改.如果您想知道如何阅读文档中的“Advanced usage” section.
假设您从服务器获取一系列用户对象并使用映射插件,则绑定将如下所示:
<ul id="update-users" data-bind="foreach: users"> <li> <div><div class="item">User ID</div> <input type="text" data-bind="value: UserId" /> </div> <div><div class="item">Name</div> <input type="text" data-bind="value: Name" /> </div> <ul class="photos" data-bind="foreach: Photos.$values"> <!-- ... --> <ul> </li> </ul>
一般来说,@Greg Smith的评论是正确的.尝试丢失对象键中的$,它们可能会在某些时候与knockout中的特殊变量冲突.例如,您可以安全地用下划线替换它们.
在更一般的注意事项中,如果我是你,我会尝试删除你的JSON中的整个$id / $值的概念,它似乎没有任何用途:
[ { "Locations": [],"Photos": [],"Name": "Test User" } ]