Knockout 无法使用函数代替 ko.computed()

Knockout unable to use function instead of ko.computed()

我有一个 UI 显示一个敲除绑定复选框和一个 HTML table。根据复选框的设置和每行记录的某些属性的值,我想隐藏某些行。

我通过在 TR 上使用 knockout 的可见绑定解决了这个问题:

<tr data-bind="visible: $root.showRowBasedOnFulfillmentCriteria">

当然我有一个复选框,isOnlyFufillmentChecked:

<input type="checkbox" data-bind="checked: $root.isOnlyFulfillmentChecked, click: $root.productsRefresh" />

我首先想到通过使 showRowBasedOnFulfillmentCriteria() 成为 ko.computed 来解决这个问题,但是有一个问题。复选框(可观察)的值仅是确定行可见性所需标准的 之一。其他标准在我构建 table 时发生变化,遍历记录。

我的理解是不能给ko.computed传参数。在 Whosebug 上研究这个问题,每个人似乎都在说我可以很容易地使用一个函数,放在我的视图模型中,而不是计算。但是,功能不起作用。

当我说一个函数不起作用时,我的意思是我已经将其剥离到最基本的、可验证的示例。在我的视图模型中,showRowBasedOnFulfillmentCriteria() 写成 ko.computed:

       self.showRowBasedOnFulfillmentCriteria = ko.computed(function () {
       return false;   // false will hide the rows, true will show them.  the computed() is "known" to the markup
   }, this);

如您所见,我采用了一种非常简单的方法,只是 returning 一个布尔值,看看我是否可以控制来自计算的行的可见性。返回 false 隐藏行; return true 显示它们。但是当我将它作为一个函数来尝试时会发生什么:

       self.showRowBasedOnFulfillmentCriteria = function () {
       return false;    
    };

这里,写成一个函数,即使总是 returning false,所有行都显示 。换句话说,函数的 return 值似乎没有任何意义。在充实函数的实际代码之前,我需要知道我可以用它来替换 ko.computed.

[编辑:使用 Chrome 的调试器,在函数中设置断点,似乎函数从未被调用;当我在敲除中将 FUNCTION 绑定到可见的 属性 时,标记似乎总是采用 TRUE 值。请继续阅读...]

我是否误解了 ko.computed 可以很容易地替换为函数的说法?

该函数在与绑定到复选框的可观察对象相同的视图模型中定义(当未注释掉时),ko.computed 版本可以代替该函数并正常工作。

如果我还没有写太多的话,我对该功能的最终目标是:

self.showRowBasedOnFulfillmentCriteria = function (flag1, flag2) {
       return self.isOnlyFufillmentChecked && flag1 && flag2;    
    };

TR 绑定将如下所示:

<tr data-bind="visible: $root.showRowBasedOnFulfillmentCriteria(Criteria1, Criteria2)">

你绝对可以做到。只需在您的视图模型上创建一个函数并将其输出传递给 visible 绑定。您可以将当前行作为参数传入,也可以在您的视图模型中引用属性。

示例代码:

function ViewModel() {
  var vm = this;

  vm.hideNoFooRows = ko.observable(false);
  vm.row = ko.observableArray([
    { foo: true, val: 'Row 1' },
    { foo: false, val: 'Row 2' },
    { foo: true, val: 'Row 3' },
    { foo: false, val: 'Row 4' },
    { foo: true, val: 'Row 5' }
  ]);

  vm.isVisible = isVisible;

  function isVisible(row) {
    let hide = ko.unwrap(vm.hideNoFooRows);
    return hide ? row.foo : !hide;
  }
}

ko.applyBindings(new ViewModel());

HTML:

<table border="1" style="width: 50%">
  <tbody data-bind="foreach: row">
    <tr data-bind="visible: $parent.isVisible($data)">
      <td data-bind="text: val"></td>
      <td data-bind="text: foo"></td>
    </tr>
  </tbody>
</table>

JSFiddle:https://jsfiddle.net/thebluenile/cjmd1hp0/