17

我是KnockoutJS的新手,我一直在尝试向插件ko.observableArray()创建的生成对象中添加其他属性和方法mapping


这就是我要做的事情:

  • 我有一个 JSON 数组Users
  • ko.observableArray()用映射插件创建了
  • 我有一个为每个创建表格行的模板,User到目前为止一切都很好:o)


这是我正在尝试做的事情:

每个User都有一个名为的属性'IsActive'-我想为每个对象data-bind上的一个方法单击事件来切换此属性。User'IsActive'

这个问题看起来很有希望,但对我来说,必须在 JS 中声明整个视图模型似乎是不必要的重复(除非我必须这样做!) - 是否可以扩展生成的对象?

我更多地沿着这些思路思考,有一种方法可以声明额外的属性或方法,并让它们扩展mapping生成的对象,但本文关注的是单个对象,而不是扩展生成的数组中的对象。


这是代码: http: //jsfiddle.net/yZkSf/2/ (尚未在 JS fiddle 中工作 - 但我会继续使用它并在我得到它工作时更新此链接)。

感谢您的帮助

4

3 回答 3

13

您可以考虑多种选择。

-一种是使用create回调来控制“用户”对象的创建方式。您可以自己定义 observables 并添加额外的功能,或者在单个用户对象上调用映射插件,然后添加额外的功能。

会是这样的:http: //jsfiddle.net/rniemeyer/fkVaK/

- 否则,您可以在 viewModel 上放置“切换”功能,然后将“用户”对象传递给它。

1.3 的一个好方法是ko.dataFor与 jQuery 的 live/delegate/on 事件委托功能等一起使用。就像:http: //jsfiddle.net/rniemeyer/FkjNr/

//unobtrusive event handler
$(".toggle").live("click", function() {
    var user = ko.dataFor(this);
    if (user) {
       viewModel.toggleIsActive(user);
    }
});

如果您不想使用事件委托,则可以使用匿名函数直接传递项目,例如:http: //jsfiddle.net/rniemeyer/GpQtN/

编辑:从 2.0 开始,当使用点击/事件绑定时,当前数据会自动传递给处理程序,所以你可以这样做:

<a href="#" data-bind="click: $root.toggleIsActive"><span data-bind="text: IsActive"></span></a>
于 2011-12-06T15:58:00.753 回答
4

这就是我使用你和瑞安的答案想出的……似乎有效。请留下反馈,因为我是 Knockout 的新手并且我自己很好奇,如果这是一个好方法。

JS:

$(function() {
    $.get("users/getUsers", function(r){
        var vm = ko.mapping.fromJS(r, {
            users: {
                create: function(user){
                    var methods = {
                        toggleIsActive: function(u){u.IsActive(!u.IsActive());},
                        foo: function(u){console.log(u);},
                        bar: function(u){/*whatever*/},   
                    }
                    return $.extend(ko.mapping.fromJS(user.data), methods);
                }
            }
        });
        ko.applyBindings(vm);
    }, 'json');
});

DOM:

<!-- ko foreach: users -->
   <a href="#" data-bind="click: toggleIsActive"><span data-bind="text: IsActive"></span></a>
<!-- /ko -->
于 2012-06-27T06:27:46.470 回答
0

我找到了一种方法来做到这一点,但这意味着一旦创建了数组中的生成对象,就循环遍历它们。我更喜欢一种无需额外循环即可获得相同结果的方法。

编辑: 就像 RP Niemeyer 在他的回答中建议的那样! ;o)

无论如何,向现有对象添加属性的一种方法是使用jQuery extend()来组合对象。

首先,在一个新对象中声明额外的属性和函数:

var userModel = {
    toggleIsActive: function() {
        console.log('toggleIsActive called: before: ' + this.IsActive());
        this.IsActive(!this.IsActive());
        // todo: save!
        console.log('toggleIsActive called: after: ' + this.IsActive());
    }
}

然后,在ko.mapping.fromJS()调用之后,调用之前ko.applyBindings(),循环遍历生成的数组中的对象并扩展它们:

viewModel.users = ko.mapping.fromJSON(/* get JSON */);

for (var i = 0; i < viewModel.users().length; i++) {
    $.extend(viewModel.users()[i], userModel);
}

ko.applyBindings(viewModel);
于 2011-12-06T16:01:36.513 回答