我正在使用一些出色的Knockout实用程序函数:
http://www.knockmeout.net/2011/04/utility-functions-in-knockoutjs.html
我想做一个arrayMap来根据条件选择某些属性,例如
return ko.utils.arrayMap(myObservableArray(),function (item) { return item.Label; });
比方说,这会产生以下输出:
[null,"","SomeLabel",null,"SomeOtherLabel"]
我想根据条件选择属性,所以我尝试:
return ko.utils.arrayMap(myObservableArray(),function (item) { if (item.Label && item.Label !== "") { return item.Label; } });
然而,你最终得到一个数组,如:
[undefined,undefined,"SomeOtherLabel"]
我也试过这个:
return ko.utils.arrayMap(myObservableArray(),function (item) { return (item.Label && item.Label !== "") ? item.Label : false; });
但你得到:
[false,false,"SomeOtherLabel"]
所以我必须这样做:
var itemsWithLabels = ko.utils.arrayFilter(myObservableArray(),function (item) { return (item.Label && item.Label !== ""); }); return ko.utils.arrayMap(itemsWithLabels,function (item) { return item.Label; });
哪个会给我:
["SomeLabel","SomeOtherLabel"]
有没有更有效的方法来实现这一点,一次性使用ko.utils或类似?
解决方法
正如您所注意到的那样,对于ko.utils.arrayMap,预计您的回调会返回一些内容.所以这是一个’哑函数’,总是将回调的返回值附加到数组.返回undefined,null或false不会忽略结果数组中的值.
arrayFilter不允许修改过滤的项目:原始项目将被推送到结果数组.
简而言之,使用ko.utils.array *函数无法更有效地完成此操作.您可以将它们组合起来并使代码更加冗长,甚至可能将它们放入计算中:
var itemsWithLabels = ko.computed(function () { return ko.utils.arrayMap(ko.utils.arrayFilter(myObservableArray(),function (item) { return item.Label && item.Label.length; }),function (filteredItem) { return filteredItem.Label; }); });
但这是你能做的最好的事情.我选择先应用过滤器,然后进行映射,因为在我看来映射会比过滤更昂贵.但这只是一种预感.
也许像Underscore这样的库提供了直接执行此操作的方法.
自己编写这样的方法也相当容易(如果你愿意的话可以把它放在ko.utils中)
ko.utils.arrayMapFilter = function (array,mapping) { array = array || []; var result = [],mapResult; for (var i = 0,j = array.length; i < j; i++) { mapResult = mapping(array[i]); if (mapResult) { result.push(mapResult); } } return result; },
你的映射回调现在可以返回虚假值,如0,“”,null或undefined,它们不会在数组中结束.
如果你想要允许上面的一些值(比如0或“”),那么只需更改一行:
if (mapResult)
更严格的事情,如:
if (mapResult !== undefined && mapResult !== null)