Knockout deferUpdates 与“if"绑定冲突 [英] Knockout deferUpdates conflict with 'if' binding
问题描述
我经常在淘汰赛中使用 if
绑定来隐藏某些东西,另外还有一个好处是我不需要担心 if
中的空引用错误.在此示例中,如果 address()
为 null,则整个块将被删除,这样您就不必为每个属性处理 null 检查.如果我使用了 visible
绑定,情况就不会如此.
你住在:<p data-bind="text: address().street.toUpperCase()"></p>
这是上面最简单的情况 - 是的,我通常会将这种模式与 <!-- ko -->
注释语法一起使用.
实际上导致我出现问题的是当我使用更复杂的 computed
值并启用 ko.options.deferUpdates
选项时:
你住在:<p data-bind="text: address().street.toUpperCase()"></p>
这个 computed
observable 的最简单实现可能是这样的:
this.hasAddress = ko.computed(function () { return _this.address() != null; });
这一切都很好,直到我执行以下操作:
<块引用>1) 在创建 observables 之前设置 ko.options.deferUpdates = true
.
2) address()
将以 null 开始,一切都很好
3) 将 address()
设置为 { street: '123 My Street' }
.再次一切正常.
4) 将 address()
重置为 null.我得到一个空错误,因为 address().street
是空 :-(
这是一个说明问题的小提琴:https://jsfiddle.net/g5gvfb7x/2/一个>
不幸的是,由于微任务运行的顺序,它试图在 if
绑定之前重新计算 text
绑定,所以你仍然得到一个 null通常不会发生的错误.
我对此有点害怕,因为我经常使用这种模式:-(
当使用 deferUpdates
时,Knockout 在内部使用 dirty
事件来通知所有计算出的 observables它们的依赖关系并安排更新,这以深度优先的顺序发生.出现这里的问题是因为绑定忽略了 dirty
事件并等待 change
事件,这将以广度优先顺序发生.
修复必须在 Knockout 中进行,以使绑定响应 dirty
事件.这已经为即将到来的版本 (3.5.0) 签入:https://github.com/knockout/knockout/issues/2226
I very often use the if
binding in knockout to hide something, with the added bonus that I don't need to worry about null reference errors inside the if
. In this example if address()
is null then the whole block is removed so you avoid having to deal with null checking for every property. This would not be the case had I used the visible
binding.
<div data-bind="if: address()">
You live at:
<p data-bind="text: address().street.toUpperCase()"></p>
</div>
This is the simplest case above - and yes I would generally use this pattern with the <!-- ko -->
comment syntax.
What is actually causing me problems is when I use a more complex computed
value and enable the ko.options.deferUpdates
option :
<div data-bind="if: hasAddress()">
You live at:
<p data-bind="text: address().street.toUpperCase()"></p>
</div>
The simplest implementation of this computed
observable might be something like this :
this.hasAddress = ko.computed(function () { return _this.address() != null; });
This all works great until I do the following:
1) set
ko.options.deferUpdates = true
before creating the observables.2)
address()
will start off as null and everything is fine3) set
address()
to{ street: '123 My Street' }
. Again everything works fine.4) reset
address()
to null. I get a null error becauseaddress().street
is null :-(Here is a fiddle to illustrate the problem : https://jsfiddle.net/g5gvfb7x/2/
It seems that unfortunately due to the order in which the micro-tasks runs it tries to recalculate the text
binding before the if
binding and so you still get a null error that normally wouldn't occur.
I'm a little scared about this since I use this pattern a lot :-(
When using deferUpdates
, Knockout internally uses a dirty
event to notify all computed observables of a change in their dependencies and to schedule updates, which happens in depth-first order. The problem here occurs because bindings ignore the dirty
event and wait for a change
event, which will happen in a breadth-first order.
The fix has to happen in Knockout to make bindings respond to the dirty
events. This has already been checked in for the upcoming version (3.5.0): https://github.com/knockout/knockout/issues/2226
这篇关于Knockout deferUpdates 与“if"绑定冲突的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!