我一直在尝试使用订阅来执行Checkall和UnCheckall复选框,我在部分成功时这样做但在处理subscribe
时我无法在几种情况下找到解决方法。
使用subscribe:
我在这里可以检查所有取消选中所有但是当我取消选中一个子复选框时,test1
或test2
我需要取消选中我的父复选框name
,如果我检查,则在下一轮test1
应检查父复选框,即保持条件检查两个子复选框。
小提琴:Click Here
ViewModel:
self.selectedAllBox.subscribe(function (newValue) {
if (newValue == true) {
ko.utils.arrayForEach(self.People(), function (item) {
item.sel(true);
});
} else {
ko.utils.arrayForEach(self.People(), function (item) {
item.sel(false);
});
}
});
使用computed
可以很容易地完成相同的场景,但是由于某些性能问题,我需要使用subscribe
,这是最好的方式,它不会像计算onload那样触发。
参考:使用计算相同的内容完美检查Fiddle
我尝试在单独的复选框绑定中使用change
事件,但到现在为止它已经死了。
感谢任何帮助。
答案 0 :(得分:2)
您的订阅仅适用于selectedAllBox上的编辑。要做你想做的事,你也需要在每个Person复选框上订阅,检查正确的条件,并在那里适当的情况下取消选中selectedAllBox。
奇怪的是,这是可以接受的但是使用computed()不是。也许你应该重新考虑你的那部分答案。我宁愿计算一个" isAllSelected"基于我的viewModel状态的值,然后将selectedAllBox绑定到该。
答案 1 :(得分:1)
计算方法是执行此操作的正确方法。您可以使用pureComputed
并使用rateLimit
来改善一些性能问题。两者都需要更新版本的Knockout而不是你的例子中使用的2.2.1(分别为3.2和3.1)。
self.SelectAll = ko.pureComputed({
read: function() {
var item = ko.utils.arrayFirst(self.People(), function(item) {
return !item.Selected();
});
return item == null;
},
write: function(value) {
ko.utils.arrayForEach(self.People(), function (person) {
person.Selected(value);
});
}
}).extend({rateLimit:1});
答案 2 :(得分:1)
几年前,我在自己的应用程序中使用手动订阅解决了类似的问题。虽然计算出的可观察方法简洁易懂,但是当存在大量项目时,其性能较差。希望下面的代码能说明一切:
function unsetCount(array, propName) {
// When an item is added to the array, set up a manual subscription
function addItem(item) {
var previousValue = !!item[propName]();
item[propName]._unsetSubscription = item[propName].subscribe(function (latestValue) {
latestValue = !!latestValue;
if (latestValue !== previousValue) {
previousValue = latestValue;
unsetCount(unsetCount() + (latestValue ? -1 : 1));
}
});
return previousValue;
}
// When an item is removed from the array, dispose the subscription
function removeItem(item) {
item[propName]._unsetSubscription.dispose();
return !!item[propName]();
}
// Initialize
var tempUnsetCount = 0;
ko.utils.arrayForEach(array(), function (item) {
if (!addItem(item)) {
tempUnsetCount++;
}
});
var unsetCount = ko.observable(tempUnsetCount);
// Subscribe to array changes
array.subscribe(function (changes) {
var tempUnsetCount = unsetCount();
ko.utils.arrayForEach(changes, function (change) {
if (change.moved === undefined) {
if (change.status === 'added') {
if (!addItem(change.value))
tempUnsetCount++;
} else {
if (!removeItem(change.value))
tempUnsetCount--;
}
}
});
unsetCount(tempUnsetCount);
}, null, 'arrayChange');
return unsetCount;
}
您仍然会在viewmodel中使用计算的observable作为select-all值,但现在它只需要检查未选择的计数:
self.unselectedPeopleCount = unsetCount(self.People, 'Selected');
self.SelectAll = ko.pureComputed({
read: function() {
return self.People().length && self.unselectedPeopleCount() === 0;
},
write: function(value) {
ko.utils.arrayForEach(self.People(), function (person) {
person.Selected(value);
});
}
}).extend({rateLimit:0});