【问题标题】:How to define a custom binding who use previous value to determine class in Knockout?如何定义使用先前值来确定 Knockout 中的类的自定义绑定?
【发布时间】:2013-02-24 19:34:49
【问题描述】:

我需要绑定一个带有敲除的表格,如果新值高于或低于之前的值,我希望表格单元格获得不同的 css 类。

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

【问题讨论】:

  • 你能多描述一下这个场景吗?以前是什么意思,在同一行或同一列上?示例数据结构也会有所帮助。

标签: javascript knockout.js


【解决方案1】:

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

当然,这只有在绑定属性是可观察的情况下才有效。

【讨论】:

    【解决方案2】:

    我研究了淘汰赛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,这足以弄清楚很多事情。
    • @VladStirbu 看来你知道我需要什么,能详细说明一下吗?
    • Jeff Mercado 已经answered 的问题。扩展要跟踪的值,然后将单元格绑定到 cssClass 函数data-bind="css: cssClass"
    【解决方案3】:

    您可以做的是创建一个扩展器来扩展您希望跟踪其先前值的可观察对象。然后,您可以检查先前的值以按照您的意愿进行操作。

    只需传入将保存前一个值的属性的名称。

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

    【讨论】:

    • Jeff:这对我来说看起来很有希望,但是我从 ko.extenders.previousValue 中得到的每一行都是空值。无法弄清楚我哪里出错了。
    • Ask a new question 并参考此答案并在此处显示其余代码。我想不出任何这不起作用的简单情况。也许你的代码中的其他东西干扰了绑定,或者你只是绑定到了错误的 observables。
    猜你喜欢
    • 1970-01-01
    • 2018-01-09
    • 2015-05-23
    • 2023-03-12
    • 1970-01-01
    • 1970-01-01
    • 2014-06-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多