如何定义使用先前值来确定Knockout中的类的自定义绑定?

时间:2013-02-24 19:34:50

标签: javascript knockout.js

我需要使用knockout绑定一个表,如果新值高于或低于前一个值,我希望表格单元格获得不同的css类。

我想到了不同的可能性,例如将之前的值存储在bindingContext中并且有一个返回正确类的函数,但是是否可以添加一个自定义绑定处理程序来接收先前的值和新值? / p>

3 个答案:

答案 0 :(得分:4)

尽管JeffSł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);
    });
  }
};

当然,只有绑定属性是可观察的时才会有效。

答案 1 :(得分:2)

我查看了淘汰赛source,我想你无法访问bindingHandler的update方法中的先前值,但是你可以将它存储在元素

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
    }
};

答案 2 :(得分:2)

您可以做的是创建一个扩展器来扩展您希望跟踪之前值的可观察量。然后,您可以根据需要检查上一个值。

只需传入将保留先前值的属性名称。

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);
}