简体   繁体   English

在Knockout.JS中按值绑定

[英]Binding by value in Knockout.JS

I'm new to Knockout.JS and I have this scenario: 我是Knockout.JS新手,我有这种情况:

I have an array of objects in my ViewModel, like this: 我的ViewModel中有一个对象数组,如下所示:

var viewModel = {
    people : ko.observableArray([
        {id = 1, name = 'John'},
        {id = 2, name = 'Alice'},
        {id = 3, name = 'Tommy'}
    ])
}

What I'm trying to do is binding to elements of the people array "by id", rather than enumerating it with a foreach or similar. 我想做的是“按id”绑定到people数组的元素,而不是用foreach或类似的方法枚举它。 I'd like to do something like: 我想做类似的事情:

<span data-bind="text: people()[id=2].name"></span>

or something similar. 或类似的东西。 In other words I'd like to get a specific item of which I know a "key" ( id in this case). 换句话说,我想得到一个我知道“键”(在这种情况下为id )的特定项。 Is this possible? 这可能吗?

Im not sure why you would fetch a specific person in the data-bind, but you need some logic to take your ID as a paremeter, and return the person you would like to display. 我不确定为什么要在数据绑定中获取特定人员,但是您需要一些逻辑来将您的ID用作参数,然后返回要显示的人员。 I made an example with binding to a specific person, and listing the full array. 我举了一个绑定到特定人并列出完整数组的示例。

JSFiddle runnable example JSFiddle可运行示例

function peopleModel(){
 var self = this;

 self.people =  ko.observableArray([
    {id: 1, name: 'John'},
    {id: 2, name: 'Alice'},
    {id: 3, name: 'Tommy'}
 ]);

 self.personById = function(id){
    return self.people().find(function(p){
    return p.id === id;
  });
 };
};

ko.applyBindings(new peopleModel());

<span data-bind="text: personById(2).name"></span>

<table>
 <tbody data-bind="foreach: people">
   <tr>
     <td data-bind="text: id"></td>
     <td data-bind="text: name"></td>
   </tr>
 </tbody>
</table>

Yes, it's possible. 是的,有可能。 For example you can create computed to have your array indexed by id: 例如,您可以创建computed以使数组按id索引:

viewModel.people.byId = ko.computed(function(){
  return viewModel.people().reduce(function(acc, obj){
    acc[obj.id] = obj;
    return acc;
  }, {});
});

..and refer particular person in the markup as: ..并将标记中的特定人称为:

<span data-bind="text: people.byId()['person_id'].name"></span>

The computed may be attached either to viewModel or to the observable array itself (I prefer the second option). computed可以附加到viewModel或可观察数组本身(我更喜欢第二种选择)。

Fiddle 小提琴

The model as you presented doesn't enumerate by key, so you would have to iterate through the items to find by key. 您提供的模型不是按键枚举的,因此您必须遍历所有项以按键查找。

If you don't want to constantly do that, you can employ one of 2 similar methods to iterate on array change: 如果您不想一直这样做,则可以采用以下两种类似方法之一来迭代数组更改:

  • use ko.computed 使用ko.computed
  • use observableArray.subscribe 使用observableArray.subscribe

Computed should be something like this: 计算应该是这样的:

viewModel.peope_by_id = ko.computed(function () {
    var result = {};
    ko.utils.arrayFilter(viewModel.people, function(item){
        result[item.id] = item;
    });
    return result;
});

and subscribe is pretty similar, except that it's updating non-ko model's slot: 和subscription非常相似,除了它正在更新non-ko模型的广告位:

viewModel.peope.subscribe(function () {
    viewModel.peope_by_id = {};
    ko.utils.arrayFilter(viewModel.people, function(item){
        viewModel.peope_by_id[item.id] = item;
    });
});

This is not a big deal and performance-wise you probably will not notice it, unless you have way many people in the data. 这不是什么大问题,从性能角度来看,除非您在数据中拥有很多人,否则您可能不会注意到它。 If you don't want to iterate at all, you'll have to change the data model or use case. 如果您根本不想迭代,则必须更改数据模型或用例。 Say by using $index instead of id to address the items. 通过使用$index而不是id来解决问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM