假设我有两个视图模型,每个模型都有一个可观察的属性,代表不同但相似的数据。
function site1Model(username) {
this.username = ko.observable(username);
....
}
function site2Model(username) = {
this.username = ko.observable(username);
....
}
这些视图模型是独立的,不一定相互链接,但在某些情况下,第三个视图模型会在它们之间创建链接。
function site3Model(username) = {
this.site1 = new site1Model(username);
this.site2 = new site2Model(username);
// we now need to ensure that the usernames are kept the same between site1/2
...
}
以下是我提出的一些选项。
使用一个计算的 observable 读取一个并写入两个:
site3Model.username = ko.computed({ read: function() { return this.site1.username(); // assume they are always the same }, write: function(value) { this.site1.username(value); this.site2.username(value); }, owner: site3Model }
只要更改始终通过计算,这将使值保持同步。但是如果一个底层的 observable 被直接改变了,它就不会这样做。
使用该
subscribe
方法相互更新:site3Model.site1.username.subscribe(function(value) { this.site2.username(value); }, site3Model); site3Model.site2.username.subscribe(function(value) { this.site1.username(value); }, site3Model);
只要值相同时可观察对象抑制通知,这就会起作用;否则你最终会陷入无限循环。您也可以更早地进行检查:
if (this.site1.username() !== value) this.site1.username(value);
这还有一个问题,即可观察对象必须简单(如果它们本身是可观察对象,它将无法正常工作site1
)site2
。用于
computed
进行订阅和更新:site3Model.username1Updater = ko.computed(function() { this.site1.username(this.site2.username()); }, site3Model); site3Model.username2Updater = ko.computed(function() { this.site2.username(this.site1.username()); }, site3Model);
这种格式允许我们拥有其他依赖项。例如,我们可以 make
site1
和site2
observables 然后使用this.site1().username(this.site2().username());
这种方法还需要检查相等性以避免无限循环。如果我们不能依赖 observable 来做到这一点,我们可以在计算中检查,但会在我们正在更新的 observable 上添加另一个依赖项(直到类似observable.peek
的东西可用)。这种方法也有一个缺点,就是最初运行一次更新代码来设置依赖关系(因为这就是computed
工作方式)。
由于我觉得所有这些方法都有缺点,有没有另一种方法可以简单(少于 10 行代码)、高效(不运行不必要的代码或更新)和灵活(处理多个级别的 observables )?