我正在尝试过滤我的users
observableArray,它有一个嵌套关键字observableArray
基于我的viewModel上的关键字observableArray。
当我尝试使用ko.utils.arrayForEach
时,我收到了堆栈溢出异常。请参阅下面的代码,也发布在this jsfiddle
function User(id, name, keywords){
return {
id: ko.observable(id),
name: ko.observable(name),
keywords: ko.observableArray(keywords),
isVisible: ko.dependentObservable(function(){
var visible = false;
if (viewModel.selectedKeyword() || viewModel.keywordIsDirty()) {
ko.utils.arrayForEach(keywords, function(keyword) {
if (keyword === viewModel.selectedKeyword()){
visible = true;
}
});
if (!visible) {
viewModel.users.remove(this);
}
}
return visible;
})
}
};
function Keyword(count, word){
return{
count: ko.observable(count),
word: ko.observable(word)
}
};
var viewModel = {
users: ko.observableArray([]),
keywords: ko.observableArray([]),
selectedKeyword: ko.observable(),
keywordIsDirty: ko.observable(false)
}
viewModel.selectedKeyword.subscribe(function () {
if (!viewModel.keywordIsDirty()) {
viewModel.keywordIsDirty(true);
}
});
ko.applyBindings(viewModel);
for (var i = 0; i < 500; i++) {
viewModel.users.push(
new User(i, "Man " + i, ["Beer", "Women", "Food"])
)
}
viewModel.keywords.push(new Keyword(1, "Beer"));
viewModel.keywords.push(new Keyword(2, "Women"));
viewModel.keywords.push(new Keyword(3, "Food"));
viewModel.keywords.push(new Keyword(4, "Cooking"));
查看代码:
<ul data-bind="template: { name: 'keyword-template', foreach: keywords }"></ul><br />
<ul data-bind="template: { name: 'user-template', foreach: users }"></ul>
<script id="keyword-template" type="text/html">
<li>
<label><input type="radio" value="${word}" name="keywordgroup" data-bind="checked: viewModel.selectedKeyword" /> ${ word }<label>
</li>
</script>
<script id="user-template" type="text/html">
<li>
<span data-bind="visible: isVisible">${ $data.name }</span>
</li>
</script>
答案 0 :(得分:5)
您的isVisible
dependentObservable已经创建了对自身的依赖,并递归尝试根据此行评估自己:
if (!visible) {
viewModel.users.remove(this);
}
因此,这会创建对viewModel.users的依赖,因为remove必须访问observableArray的底层数组才能删除用户。在修改阵列时,会通知订户,其中一个订户就是自己。
通常最好不要更改dependentObservable中任何observable的状态。您可以手动订阅对dependentObservable的更改并在那里进行更改(前提是dependentObservable不依赖于您要更改的内容)。
但是,在这种情况下,我可能会在viewModel级别创建一个名为filteredUsers
的dependentObservable。然后,返回已过滤的用户数组的版本。
可能看起来像这样:
viewModel.filteredUsers = ko.dependentObservable(function() {
var selected = viewModel.selectedKeyword();
//if nothing is selected, then return an empty array
return !selected ? [] : ko.utils.arrayFilter(this.users(), function(user) {
//otherwise, filter on keywords. Stop on first match.
return ko.utils.arrayFirst(user.keywords(), function(keyword) {
return keyword === selected;
}) != null; //doesn't have to be a boolean, but just trying to be clear in sample
});
}, viewModel);
您也不应该需要脏标志,因为当他们访问的任何可观察对象发生更改时,将重新触发dependentObservables。因此,由于它访问selectedKeyword,只要selectedKeyword发生更改,它就会被重新评估。
http://jsfiddle.net/rniemeyer/mD8SK/
我希望我能正确理解你的情景。