KnockoutJS:将 Observable 属性和函数添加到映射生成的 ObservableArray 中的对象
Posted
技术标签:
【中文标题】KnockoutJS:将 Observable 属性和函数添加到映射生成的 ObservableArray 中的对象【英文标题】:KnockoutJS: Adding Observable Properties and Functions to objects in a mapping generated ObservableArray 【发布时间】:2012-01-14 03:59:43 【问题描述】:我是KnockoutJS 的新手,我一直在尝试向ko.observableArray()
中由mapping
插件创建的生成对象添加其他属性和方法。
这是我的目标:
我有一个Users
的 JSON 数组
我用映射插件创建了ko.observableArray()
我有一个为每个User
创建表格行的模板,到目前为止一切顺利:o)
这是我想要做的:
每个User
都有一个名为'IsActive'
的属性 - 我想data-bind
一个点击事件到每个User
对象上的一个方法,该方法可以切换这个'IsActive'
属性。
This question looked promising,但在 JS 中声明整个视图模型对我来说似乎是不必要的重复(除非我必须这样做!) - 是否可以只扩展生成的对象?
I was thinking more along these lines,有一种方法可以声明其他属性或方法,并让它们扩展mapping
生成的对象,但本文关注的是单个对象,而不是扩展生成数组中的对象。
代码如下: http://jsfiddle.net/yZkSf/2/(尚未在 JS fiddle 中工作 - 但我会继续使用它,并在它工作时更新此链接)。
感谢您的帮助
【问题讨论】:
【参考方案1】:您可以考虑多种选择。
-一种是使用create
callback 来控制“用户”对象的创建方式。您可以自己定义可观察对象并添加额外功能,也可以在单个用户对象上调用映射插件,然后添加额外功能。
类似于: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>
【讨论】:
完美! - 我接近了create:
回调,但文档侧重于修改子数组,我看不到如何扩充基础对象。非常感谢【参考方案2】:
这是我使用您和 Ryan 的答案得出的结果……似乎有效。请留下反馈,因为我是 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 -->
【讨论】:
【参考方案3】:我找到了一种方法来做到这一点,但这意味着一旦创建了数组中的生成对象,就循环遍历它们。我更喜欢一种无需额外循环即可获得相同结果的方法。
编辑: 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);
【讨论】:
以上是关于KnockoutJS:将 Observable 属性和函数添加到映射生成的 ObservableArray 中的对象的主要内容,如果未能解决你的问题,请参考以下文章
Knockoutjs之observable和applyBindings的使用
Knockoutjs之observable和applyBindings的使用
KnockoutJS 查找 ko.observable() 长度
KnockoutJs observable array 通过计算 observable 和节流