Javascript 一个计算出的;“睡觉”;直到一些初始化完成
我有一个复杂的viewmodel,它包含几个可观察属性、数组等。我有一个计算的可观察属性,它有几个依赖项。在定义时不能执行计算的内部逻辑,而只能在模型完全初始化之后执行 例如: 图像用户可以从多个大陆、国家或城市中选择一个的表单。每次选定某些大陆时,国家列表应仅包含位于选定大陆上的国家,城市等也应如此 为了优化HTTP流量,初始列表作为页面的一部分填充,因此不需要初始JSON请求Javascript 一个计算出的;“睡觉”;直到一些初始化完成,javascript,knockout.js,Javascript,Knockout.js,我有一个复杂的viewmodel,它包含几个可观察属性、数组等。我有一个计算的可观察属性,它有几个依赖项。在定义时不能执行计算的内部逻辑,而只能在模型完全初始化之后执行 例如: 图像用户可以从多个大陆、国家或城市中选择一个的表单。每次选定某些大陆时,国家列表应仅包含位于选定大陆上的国家,城市等也应如此 为了优化HTTP流量,初始列表作为页面的一部分填充,因此不需要初始JSON请求 var viewModel = function(data) { this.Continents = ko.ob
var viewModel = function(data) {
this.Continents = ko.observableArray(data.Continents);
this.Countries = ko.observableArray(data.Countries);
this.Cities = ko.observableArray(data.Cities);
this.SelectedContinents = ko.observableArray(data.SelectedContinents);
this.SelectedCountries = ko.observableArray(data.SelectedCountries);
this.SelectedCities = ko.observableArray(data.SelectedCities);
this.LoadFromServer = function() {
$.post({
url: '/reloadLists',
data: { continents: this.SelectedContinents(), countries: this.SelectedCountries(), cities: this.SelectedCities() },
success: function(result) {
this.Continents(result.Continents);
this.Countries(result.Countries);
this.Cities(result.Cities);
}
});
};
ko.computed(function() {
this.LoadFromServer();
}, this);
}
...
var data = ... // initial data rendered on server-side
var model = new viewModel(data);
ko.applyBindings(model);
使用这种方法,问题在于当computed最初执行rad函数时,LoadFromServer逻辑也会在模型初始化时执行。这样就有了冗余的往返,因为初始列表已经在模型中了
我现在能想到的唯一解决方案是引入一个标志来阻止具体的逻辑,直到需要它为止。这个标志不应该是可观察的,因为当我在构造函数末尾将它设置为true时,计算出的值将被重新计算,冗余的往返将再次进行。但是,如果该标志不是可观察的,那么我必须确保在初始化时捕获依赖项,以便它能够在之后对更改做出反应。把所有这些放在一起,currenct结果看起来像这样
var viewModel = function(data) {
var initialized = false;
this.Continents = ko.observableArray(data.Continents);
this.Countries = ko.observableArray(data.Countries);
this.Cities = ko.observableArray(data.Cities);
this.SelectedContinents = ko.observableArray(data.SelectedContinents);
this.SelectedCountries = ko.observableArray(data.SelectedCountries);
this.SelectedCities = ko.observableArray(data.SelectedCities);
this.LoadFromServer = function() {
$.post({
url: '/reloadLists',
data: { continents: this.SelectedContinents(), countries: this.SelectedCountries(), cities: this.SelectedCities() },
success: function(result) {
this.Continents(result.Continents);
this.Countries(result.Countries);
this.Cities(result.Cities);
}
});
};
ko.computed(function() {
var catchDependencies = [this.SelectedContinents(), this.SelectedCountries(), this.SelectedCities()];
if (!initialized) return;
this.LoadFromServer();
}, this);
initialized = true;
}
从技术上讲,这是一个很好的解决方案,但我不太喜欢它,因为它对我来说有些味道
对于这些场景,有没有更好的解决方案?或者我不应该尝试优化事情,让初始AJAX加载,而不是服务器端的initialo数据呈现?嗨,我不确定这是否是最好的方法,但它可以工作 所以我的方法是,我创建了一个名为
isComplete
的标志,如果这是真的,那么显示计算值,否则显示默认值。这适用于HTML,以便绑定不会失败
此外,我还添加了一个按钮,用于注册计算值。它也可以在订阅某个值时执行此操作
var ViewModel=函数(第一个,最后一个){
var self=这个;
self.firstName=ko.可观察(第一);
self.lastName=ko.可观察(last);
self.isComplete=ko.可观察(假);
//计算注册部分
self.registerComputed=函数(){
如果(!self.hasOwnProperty(“全名”)){
self.fullName=ko.computed(函数(){
返回此.firstName()+“”+此.lastName();
},这个);
}
self.isComplete(真);
}
};
ko.应用绑定(新视图模型(“行星”、“地球”)代码>
body{font-family:arial;字体大小:14px;}
.liveExample{填充:1em;背景色:#eeedd;边框:1px实心#CCC;最大宽度:655px;}
.liveExample输入{font-family:Arial;}
.liveExample b{font-weight:bold;}
.liveExample p{页边距顶部:0.9em;页边距底部:0.9em;}
.liveExample选择[多个]{宽度:100%;高度:8em;}
.liveExample h2{页边空白:0.4em;字体重量:粗体;字体大小:1.2em;}
名字:
姓氏:
你好
嗨,我不确定这是否是最好的方法,但它确实有效
所以我的方法是,我创建了一个名为isComplete
的标志,如果这是真的,那么显示计算值,否则显示默认值。这适用于HTML,以便绑定不会失败
此外,我还添加了一个按钮,用于注册计算值。它也可以在订阅某个值时执行此操作
var ViewModel=函数(第一个,最后一个){
var self=这个;
self.firstName=ko.可观察(第一);
self.lastName=ko.可观察(last);
self.isComplete=ko.可观察(假);
//计算注册部分
self.registerComputed=函数(){
如果(!self.hasOwnProperty(“全名”)){
self.fullName=ko.computed(函数(){
返回此.firstName()+“”+此.lastName();
},这个);
}
self.isComplete(真);
}
};
ko.应用绑定(新视图模型(“行星”、“地球”)代码>
body{font-family:arial;字体大小:14px;}
.liveExample{填充:1em;背景色:#eeedd;边框:1px实心#CCC;最大宽度:655px;}
.liveExample输入{font-family:Arial;}
.liveExample b{font-weight:bold;}
.liveExample p{页边距顶部:0.9em;页边距底部:0.9em;}
.liveExample选择[多个]{宽度:100%;高度:8em;}
.liveExample h2{页边空白:0.4em;字体重量:粗体;字体大小:1.2em;}
名字:
姓氏:
你好
试试看
阅读更多 试试看
阅读更多 您需要使用的是延迟评估
选项:
可选。如果此选项为true,则在某个对象实际尝试访问其值或手动订阅该值之前,不会计算计算出的可观测值。默认情况下,在创建过程中,计算的可观察对象的值会立即确定
Te idea正在设置此选项,并在初始化完成时手动访问可观察对象,使其“变为活动”。当然,您必须将其存储在“private”变量中才能访问它
另请参见:您需要使用的是延迟评估
选项:
可选。如果此选项为true,则在某个对象实际尝试访问其值或手动订阅该值之前,不会计算计算出的可观测值。默认情况下,在创建过程中,计算的可观察对象的值会立即确定
Te idea正在设置此选项,并在初始化完成时手动访问可观察对象,使其“变为活动”。当然,您必须将其存储在“private”var中
ko.computed(function() {
if(ko.computedContext.isInitial()) return;
this.LoadFromServer();
}, this);
this.SelectedContinents.subscribe(this.LoadFromServer);
this.SelectedCountries.subscribe(this.LoadFromServer);
this.SelectedCities.subscribe(this.LoadFromServer);