【发布时间】:2013-02-24 19:34:49
【问题描述】:
我需要绑定一个带有敲除的表格,如果新值高于或低于之前的值,我希望表格单元格获得不同的 css 类。
我想到了不同的可能性,例如将先前的值存储在 bindingContext 中并有一个返回正确类的函数,但是是否可以添加一个自定义绑定处理程序来接收先前的值和新的值?
【问题讨论】:
-
你能多描述一下这个场景吗?以前是什么意思,在同一行或同一列上?示例数据结构也会有所帮助。
我需要绑定一个带有敲除的表格,如果新值高于或低于之前的值,我希望表格单元格获得不同的 css 类。
我想到了不同的可能性,例如将先前的值存储在 bindingContext 中并有一个返回正确类的函数,但是是否可以添加一个自定义绑定处理程序来接收先前的值和新的值?
【问题讨论】:
虽然Jeff 和Sławomir 的答案可行,但我找到了一个替代方案,它不需要对视图模型进行任何更改,也不依赖于更改 DOM 元素对象。
function subscribeToPreviousValue(observable, fn) {
observable.subscribe(fn, this, 'beforeChange');
}
ko.bindingHandlers['bindingWithPrevValue'] = {
init: function (element, valueAccessor) {
var observable = valueAccessor();
var current = observable();
console.log('initial value is', current);
subscribeToPreviousValue(observable, function (previous) {
console.log('value changed from', previous, 'to', current);
});
}
};
当然,这只有在绑定属性是可观察的情况下才有效。
【讨论】:
我研究了淘汰赛source,我想你不能在 bindingHandler 的更新方法中访问以前的值,但你可以将它存储在元素中
ko.bindingHandlers['bindingWithPrevValue'] = {
update: function (element, valueAccessor) {
var prevValue = $(element).data('prevValue');
var currentValue = valueAccessor();
$(element).data('prevValue', currentValue());
// compare prevValue with currentValue and do what you want
}
};
【讨论】:
update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) 让您可以访问整个 viewModel 和 bindingContext,这足以弄清楚很多事情。
data-bind="css: cssClass"
您可以做的是创建一个扩展器来扩展您希望跟踪其先前值的可观察对象。然后,您可以检查先前的值以按照您的意愿进行操作。
只需传入将保存前一个值的属性的名称。
ko.extenders.previousValue = function (target, propertyName) {
var previousValue = ko.observable(null);
target[propertyName] = ko.computed(previousValue);
target.subscribe(function (oldValue) {
previousValue(oldValue);
}, target, 'beforeChange');
return target;
};
然后使用它:
function ViewModel() {
this.value = ko.observable('foo').extend({ previousValue: 'previousValue' });
}
var vm = new ViewModel();
console.log(vm.value()); // 'foo'
console.log(vm.value.previousValue()); // null
vm.value('bar');
console.log(vm.value()); // 'bar'
console.log(vm.value.previousValue()); // 'foo'
在你的情况下,你可能会使用这样的东西:
function TableCell(value) {
this.value = ko.observable(value).extend({ previousValue: 'previousValue' });
this.cssClass = ko.computed(function () {
// I'm assuming numbers
var current = Number(this.value()),
previous = Number(this.value.previousValue());
if (current < previous)
return 'lower';
else if (current > previous)
return 'higher';
}, this);
}
【讨论】: