在afterRender回调函数中设置ViewModel数据值会破坏Knockout.js绑定

时间:2011-08-29 14:11:26

标签: knockout.js

我有一个非常复杂的jquery模板,我通过knockout.js框架与基于javascript的ViewModel数据绑定。实际上,我在另一个observableArray中有ViewModelViewModel个对象绑定到我的模板。

在我的模板中,我有几个DOM元素,当它们的值发生变化时会触发某些事件。例如,我有一个单选按钮设置,当选择一个值时,它会改变选择列表的绑定(以及启用),这反过来通过改变各种可观察的属性来清除文本框的值(以及启用)在我的界限内ViewModel。这些触发器有助于为最终用户指导UX流程,并确保根据需要保存或清除某些值。这一切都很好。

...然而

当我从我的数据库中检索初始数据并填充我的ViewModels时,然后将ViewModels绑定到模板,触发器会触发它们。但是,我希望由于触发器触发而清除基础可观察值。因此,我设计的是一种初始设置ViewModel的{​​{1}}可观察值为IsInitialData的方法,我的触发器用它来确定是否清除某些值。但是,我希望在完成模板绑定之后,以及在执行任何用户交互之前,将这些属性设置为true

对我来说最有意义的是使用false回调将afterRender属性设置为IsInitialData。这样,我的触发器会在绑定初始数据后正常触发。我的false回调函数如下所示:

afterRender

有趣的是,即使设置了值,我也可以在上述函数中读取该值。

...然而

一旦我在上面的function resetIsInitialDataAttribute(nodesArray, dataValue) { alert(dataValue.IsInitialData()); // Displays 'true' dataValue.IsInitialData(false); alert(dataValue.IsInitialData()); // Displays 'false' } 回调函数中设置了值,我的可观察绑定似乎就会中断。为了测试,我在模板中放置了一个div来序列化我的afterRender,这样我就可以显示所有observableArray的值:

ViewModel

如果我没有在<div data-bind="text: ko.toJSON(locationsViewModel.locations)"></div> 回调中设置IsInitialData属性,那么当我修改已绑定到afterRender可观察属性的DOM元素时,以上div立即显示修改后的值。但是,如果我在回调函数中设置了ViewModel属性,则上面的div不再在IsInitialData中显示任何更改的值。

有谁知道为什么在ViewModel回调函数中设置我的ViewModel属性会导致问题?在我的初始数据库绑定完成后,是否有另一种方法可以设置afterRender IsInitialData属性?我查看了jQuery.tmpl文档中的任何类型的回调,我可以使用它在绑定我的数据后发生,但没有发现任何可用的。

1 个答案:

答案 0 :(得分:6)

您的问题基本上是此问题的一个版本:https://github.com/SteveSanderson/knockout/issues/133。还描述了here

afterRender期间,元素实际上还不在DOM中。在刚刚绑定到元素的此代码(或绑定)中设置observable的值将导致重新评估该元素绑定中使用的dependentObservable。它会看到该元素不在DOM中,并认为它应该自行处理。

一个简单的解决方法是在afterRender中设置您的值,如:

setTimeout(function() { dataValue.IsInitialData(false); }, 0);

这将使当前执行完成,此时元素将在DOM中。