【问题标题】:Knockout.js: Binding to complex objectKnockout.js:绑定到复杂对象
【发布时间】:2016-12-01 23:12:55
【问题描述】:

我是 knockout.js 的新手,我正在尝试绑定到以下代表用户的对象:

{
    "$id": "1",
    "$values": [
        {
            "$id": "2",
            "Locations": {
                "$id": "3",
                "$values": []
            },
            "Photos": {
                "$id": "4",
                "$values": []
            },
            "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>

我是不是完全做错了?或者用户对 Locations 和 Photos 的对象引用可能会破坏绑定?

【问题讨论】:

  • UserId 和 Name 位于对象的“$values”部分下 - 您没有将其包含在绑定中。 $values 以 $ 开头的事实可能会让您在淘汰赛中遇到麻烦。如果您可以控制对象的生成方式,那么值得去掉 $ 来稍微整理一下。
  • 您的 self.users = 数据工作正常吗?我没有看到将 $values 数组写入您的可观察数组

标签: knockout.js


【解决方案1】:

我是不是做错了?

是的。您正在 JSON 回调中覆盖您的 observableArray,从而将其销毁:

$.getJSON(baseUri, function (data) {
    self.users = data;
});

一般来说,淘汰赛 observable 的分配方式如下:

$.getJSON(baseUri, function (data) {
    self.users(data.$values);
});

请注意,在您的情况下,data.$values 似乎包含实际数组,而不是 data 本身。

这对你的情况有用,但它并没有充分发挥淘汰赛的潜力。

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 的评论是正确的。尝试丢失对象键中的$,它们可能会在某些时候与淘汰赛中的特殊变量发生冲突。例如,您可以安全地将它们替换为下划线。

总的来说,如果我是你,我会尝试在你的 JSON 中去掉整个 $id/$values 概念,它似乎没有任何用途:

[
    {
        "Locations": [],
        "Photos": [],
        "UserId": 1,
        "Name": "Test User"
    }
]

【讨论】:

  • 谢谢,这真的很有帮助。我将检查映射插件,它看起来做了很多繁重的工作。至于 json 的格式,这是 JSON.NET 从 Entity Framework 对象生成的。我将如何去除 $id/$values 格式?
  • @verbose 我不知道,但这是另一个问题的好材料。甚至似乎以前没有人问过这个问题。
猜你喜欢
  • 1970-01-01
  • 2014-06-17
  • 2011-02-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多