执行此操作时,我意识到ko-properties的顺序非常重要,因为计算属性根据创建属性时存在的其他属性来设置其订阅.因此,如果我将一个类似于下面的isDirty-computed放在一个基类中,它总是在它所依赖的属性之前进行初始化甚至存在.无论如何,为了缩短它,我注意到我可以使用deferEvaluation来解决这个问题.
我的问题是:
在所有计算属性上使用deferEvaluation有什么缺点吗?为什么默认情况下这种行为是真的?我什么时候需要它设置为假?
我可以做到这个更好的财产吗?有关改进或以其他方式进行的任何建议吗?
或者,有没有办法显式禁用计算属性的初始化,直到创建具有其所有属性的整个对象,然后以某种方式运行它.我的意思是对我来说唯一的问题是订阅是在所有属性到位之前设置的.
注意:我正在使用KO Lite Tools进行脏跟踪
function viewmodel() { var self = this; self.isDirty = ko.computed(function () { for (var p in self) { if (self[p].isDirty) { if (self[p].isDirty()) return true; } else if (self[p].subscribe && self[p].push) { // assuming ko.observableArray for (var i = 0,j = self[p]().length; i < j; i++) { if (self[p]()[i].isDirty) { if (self[p]()[i].isDirty()) return true; } } } } return false; },this,{ deferEvaluation: true }); }
注意:注意,如果我有另一个依赖于isDirty的计算属性,则此代码将失败.这有点令人期待,但也很不幸.如果我可以在创建对象后延迟并强制所有订阅,那将会很棒.
解决方法
使用deferEvaluation时,不会立即执行ko.computed的依赖项检测,而是在每次请求值时执行.
这为动态改变依赖关系提供了强大的机制,但确实导致了增加的开销.
Ryan谈到这个有点on this page(向下滚动到第3节 – 计算可观察量的基本规则):
是否可以构造代码,以便在创建其他属性后定义ko.computed值?
如果您的主要问题是脏标记跟踪,您可以在基本VM中设置beginInit()和endInit()方法,并在endInit()中设置isDirty计算.您可能不需要beginInit(),但它提供了一个很好的钩子以保持一致性,以后可能会有用.
当然,派生的VM需要在设置其observable之前和之后调用基本init方法.我不确定您当前创建派生VM的策略是什么 – 我通常使用工厂来提供原型继承,并且我对初始化时间有这种控制.
beginInit()和endInit()的一个更简单的替代方法是简单地在派生类中提供initProperties()函数,其中定义了所有属性,并从基本VM调用该方法,然后设置isDirty computed.