Knockout deferUpdates与'if'绑定冲突

Sim*_*ver 9 knockout.js

我经常使用if敲除中的绑定来隐藏某些东西,还有额外的好处,我不需要担心里面的空引用错误if.在此示例中,如果address()为null,则删除整个块,以避免必须处理每个属性的空检查.如果我使用visible绑定,情况就不是这样了.

<div data-bind="if: address()">
    You live at:
    <p data-bind="text: address().street.toUpperCase()"></p>            
</div>
Run Code Online (Sandbox Code Playgroud)

这是上面最简单的情况 - 是的,我通常会将此模式与<!-- ko -->注释语法一起使用.

实际上导致我出现问题的是当我使用更复杂的computed值并启用该ko.options.deferUpdates选项时:

<div data-bind="if: hasAddress()">
    You live at:
    <p data-bind="text: address().street.toUpperCase()"></p>            
</div>
Run Code Online (Sandbox Code Playgroud)

这个computedobservable 最简单的实现可能是这样的:

this.hasAddress = ko.computed(function () { return _this.address() != null; }); 
Run Code Online (Sandbox Code Playgroud)

这一切都很有效,直到我执行以下操作:

1)ko.options.deferUpdates = true在创建可观察量之前设置.

2)address()将从null开始,一切都很好

3)设置address(){ street: '123 My Street' }.一切都很好.

4)重置address()为null.我得到一个null错误,因为address().street是null :-(

这是一个解释问题的小提琴:https://jsfiddle.net/g5gvfb7x/2/

似乎不幸的是,由于微任务运行的顺序,它试图在text绑定之前重新计算if绑定,因此您仍然会得到通常不会发生的空错误.


我有点害怕这个,因为我经常使用这个模式:-(

Mic*_*est 3

当使用 时deferUpdates,Knockout 在内部使用一个dirty事件来通知所有计算的可观察量其依赖项的更改并安排更新,这按深度优先顺序发生。出现此处问题的原因是绑定忽略dirty事件并等待change事件,该事件将以广度优先顺序发生。

修复必须在 Knockout 中进行,以使绑定响应事件dirty。这已经被签入即将发布的版本(3.5.0):https ://github.com/knockout/knockout/issues/2226