我是KnockoutJS的新手,我一直试图在ko.observableArray()
插件创建的mapping
中为生成的对象添加其他属性和方法。
这是我要去的地方:
Users
ko.observableArray()
User
创建表格行的模板,到目前为止一直很好:o)
以下是我要做的事情:
每个User
都有一个名为'IsActive'
的属性 - 我想data-bind
点击每个User
对象上的方法的点击事件切换此'IsActive'
} property。
This question looked promising,但似乎不必重复我必须在JS中声明整个View模型(除非我必须这样做!) - 是否可以只扩展生成的对象?
I was thinking more along these lines,其中有一种方法可以声明其他属性或方法,并让它们扩展mapping
生成的对象,但本文关注的是单个对象,而不是在生成的数组中扩展对象。
以下是代码: http://jsfiddle.net/yZkSf/2/(尚未在JS小提琴中工作 - 但我会继续使用它并在我开始工作时更新此链接。)
感谢您的帮助
答案 0 :(得分:13)
您可以考虑几个选项。
- 一个是使用create
callback来控制“用户”对象的创建方式。您可以自己定义observable并添加额外的功能,也可以在单个用户对象上调用映射插件,然后添加额外的功能。
类似于:http://jsfiddle.net/rniemeyer/fkVaK/
- 否则,您可以在viewModel上放置“toggle”功能,然后将“user”对象传递给它。
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>
答案 1 :(得分:4)
这就是我用你和Ryan的答案提出的......似乎有效。如果这是一个很好的方法,请留下反馈,因为我是Knockout的新手并且好奇自己。
$(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');
});
<!-- ko foreach: users -->
<a href="#" data-bind="click: toggleIsActive"><span data-bind="text: IsActive"></span></a>
<!-- /ko -->
答案 2 :(得分:0)
我找到了一种方法,但它意味着一旦创建它们就会循环遍历数组中生成的对象。我更喜欢一种方法,在没有额外循环的情况下实现相同的结果..
编辑: Like RP Niemeyer suggests in his answer!; 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);