Knockout deferUpdates 与“if"绑定冲突 [英] Knockout deferUpdates conflict with 'if' binding

查看:24
本文介绍了Knockout deferUpdates 与“if"绑定冲突的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我经常在淘汰赛中使用 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 fine

3) set address() to { street: '123 My Street' }. Again everything works fine.

4) reset address() to null. I get a null error because address().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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆