【问题标题】:Can you force KnockoutJS to reevaluate bindings?你能强制 KnockoutJS 重新评估绑定吗?
【发布时间】:2011-12-26 19:29:58
【问题描述】:

我在一个页面中使用了 KnockoutJS 和 MVVM,并且大多数情况下都可以使用,但是我无法让所有绑定重新评估。例如,我有一个按钮,我想在满足某些条件时启用它:

<input type="submit" value="Purchase" data-bind="{enable: IsPurchaseValid}" />

IsPurchaseValid 是我的视图模型的计算函数:

viewModel.IsPurchaseValid = ko.computed(function() {
console.log("IsPurchaseValid: function entered...");

if (this.Duration() == null ||  this.Total() <= 0 || this.SelectedPackageId() < 0) {
    console.log("IsPurchaseValid: Something is missing...");
    return false;
}

return this.IsLocalityCountValid();
}, viewModel);

该按钮在页面加载时被正确禁用,但从未重新评估。 IsLocalityCountValid 是另一个计算函数,console.log 语句表明它返回 true。 Chrome 的控制台没有显示脚本错误。

如何正确地重新评估启用绑定?我还有一个可见绑定到 !IsLocalityCountValid 的跨度,它永远不会变得可见。我觉得我错过了一些基本的东西,但无法弄清楚它可能是什么。

【问题讨论】:

  • 第二个问题,请尝试!IsLocalityCountValid()。 Knockout 只检测某些表达式中的可观察对象的名称,并且您必须在其他表达式中显式调用可观察对象,否则它会被评估为 Function,而始终是 true
  • @JeffreyYasskin - 这确实解决了第二个问题。我在“启用”问题上尝试过,但没有任何变化。
  • 你能把你的问题发一个 jsfiddle 吗?
  • 很奇怪,当我将它隔离在 JSFiddle 中时,按钮和提交都可以工作,但在实时站点中(无法共享)只有按钮有效。 jsfiddle.net/joelcochran/ssbW2

标签: mvvm knockout.js


【解决方案1】:

我有一个非常基本的 repro 可以在它工作的地方启用。 (见下面的小提琴)

我建议你检查你的 CSS。我曾经遇到过这个问题,因为我以某种方式删除了我的 button:disabled 样式。我有一个改变背景颜色和字体颜色的按钮样式,但不知何故我 删除了 button:disabled 样式....所以最终结果是当它被禁用时,它看起来与启用时完全相同。

无论如何,您可以在此处测试启用/禁用按钮:您可以在此处自己测试:http://jsfiddle.net/johnpapa/wLKS6/

当没有 CSS 干预时,我没有遇到这个问题。因此,关键可能是确保您的 CSS 类首先表现良好。

【讨论】:

  • 感谢您添加此 John,我确定这是问题的一部分。我的猜测是其中一个库的 CSS 存在这个问题。
  • 很有可能。很久以前我在使用带有 KO 的 jQuery UI 时也遇到了一些问题……结果是一个类似的问题,很容易解决。
【解决方案2】:

这可能是 KO 对您的计算值的评估没有看到所有可观察值,因此不知道何时重新评估计算值。

例如,如果 KO 发现 this.Duration 不为 null,它可能不会评估 if 块中的其他 observables,因此,如果其他 observables 发生变化,它可能不知道重新评估您的计算值。

试试这个尺寸,看看它是否有效:

viewModel.IsPurchaseValid = ko.computed(function() {
   console.log("IsPurchaseValid: function entered...");

   // Evaluate all dependent observables up front.
   // This will let KO know which observables this computed value is dependent on.
   var duration = this.Duration();
   var total = this.Total();
   var packageId = this.SelectedPackageId();
   var islocalityCountValid = this.IsLocalityCountValid();
   if (duration == null || total <= 0 || packageId < 0) {
       console.log("IsPurchaseValid: Something is missing...");
       return false;
   }

   return isLocalityCountValid;
}, viewModel);

【讨论】:

  • 发布的代码评估结果为 true,我添加了更多 console.log 语句进行验证,每次更改选择时,日志都会验证函数是否正确返回 true 或 false。所以评估正在触发,代码返回正确的值,但按钮总是被禁用。我还将绑定更改为“data-bind="{enable: IsPurchaseValid()}”,也没有更改。
【解决方案3】:

您提到IsLocalityCountValid 已更改为true,但您未提及Duration 是否已更改为非nullTotal 已更改为&gt;0SelectedPackageId 是否已更改到&gt;=0。如果它们都没有改变,Knockout 将不会重新评估 computed,因为它在需要评估 IsLocalityCountValid 之前返回 false。有关更多详细信息,请参阅http://knockoutjs.com/documentation/computedObservables.html#how_dependency_tracking_works

【讨论】:

    【解决方案4】:

    我刚刚注意到您的数据绑定语句用花括号括起来:

    data-bind="{enable: IsPurchaseValid}"
    

    尝试不使用花括号:

    data-bind="enable: IsPurchaseValid"
    

    【讨论】:

    • 我已经尝试过两种方式,有和没有 () 也是如此。这似乎是提交的一个错误。
    • 大括号在这里是可选的。
    【解决方案5】:

    所以看起来这实际上是一个错误。使用原始代码,如果将其绑定到输入类型“提交”它不起作用,但如果将其绑定到输入类型“按钮”它确实有效。我把它提交给了 KnockoutJS google group。

    编辑: 我将接受这个作为答案,但在 JSFiddle 中按钮和提交工作。我的假设是肯定存在一些跨 jquery 库冲突,因为我在实际站点中还有其他几个库在起作用。

    【讨论】:

    • 不要认为这已经完成了——它在 JSFiddle 中同时具有按钮和提交功能,但在我的实时站点中仅具有按钮。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-23
    • 2021-08-17
    • 1970-01-01
    • 2015-11-13
    • 2015-09-22
    • 1970-01-01
    相关资源
    最近更新 更多