我的示例正在运行,但我对ko.applyBindings()语句的位置感到困惑。我使用this approach从单个getJSON请求填充我的ViewModel。但是假设我需要2个getJSON请求。我移动了" var viewModel = new MyViewModel();"在getJSON之外,但ko.applyBinding()在两个getJSON方法中,我明白你不应该有2个绑定到同一个VM。我尝试在getJSON下面移动ko.applyBinding(),但没有任何效果。所以我将ko.applyBinding()放在其中一个getJSON方法中,并调用VM方法从另一个JSON调用中设置变量。它似乎有效,但我担心如果JSON请求在不同时间返回,则存在可能导致问题的时序问题。
var MyViewModel = function() {
var self = this;
self.types = ko.observableArray();
self.states = ko.observableArray();
self.loadStates = function (states){
self.states = states;
}
}
var viewModel = new MyViewModel();
$(function () {
$.getJSON('json/typeArray.json', function(jTypes){
viewModel.types = jTypes;
ko.applyBindings(viewModel);
});
$.getJSON('json/stateArray.json', function(jStates){
viewModel.loadStates(jStates);
//ko.applyBindings(viewModel);
});
});
我可以使用嵌套的JSON请求,但我希望它们能够同时执行。
为什么ko.applyBindings(viewModel)不能移动到此脚本的底部?我试过了,但我的阵列都没有填充。
更新:是的,有时间问题。有时第二个"状态"数组在UI中更新,有时则不会。它显然取决于getJSON首先返回。所以我确实需要找到解决这个问题的方法。
以下是在viewModel创建后移动applyBindings的尝试,该方法不起作用(请参阅注释):
var MyViewModel = function() {
var self = this;
self.name = "myViewModel";
self.states = ko.observableArray();
self.types = ko.observableArray();
self.loadStates = function (states){
self.states = states;
console.log("Set states in viewModel: " + self.states);
}
}
var viewModel = new MyViewModel();
ko.applyBindings(viewModel);
$(function () {
$.getJSON('json/typeArray.json', function(jTypes){
console.log("Setting types in viewModel: " + viewModel.name);
viewModel.types = jTypes;
//ko.applyBindings(viewModel);
});
$.getJSON('json/stateArray.json', function(jStates){
console.log("Setting states in viewModel: " + viewModel.name);
viewModel.loadStates(jStates);
//ko.applyBindings(viewModel);
});
});
答案 0 :(得分:1)
问题在于您将新值设置为可观察数组,并且不将新对象分配给绑定属性。
而不是分配:
viewModel.types = jTypes;
我建议使用更新:
//viewModel.types(jTypes);
viewModel.types(["type a", 'type b', 'type c']);
我创建了一个示例(请求通过setTimeout模拟),启动数组为空,“times”在1秒内更新,“状态”在2秒内更新:
var MyViewModel = function() {
var self = this;
self.name = "myViewModel";
self.states = ko.observableArray();
self.types = ko.observableArray();
}
var viewModel = new MyViewModel();
ko.applyBindings(viewModel);
//$(function () {
// $.getJSON('json/typeArray.json', function(jTypes){
// viewModel.types(jTypes);
// });
// $.getJSON('json/stateArray.json', function(jStates){
// viewModel.states(jStates);
// });
//});
//$.getJSON('json/typeArray.json', function(jTypes){
setTimeout(function() {
viewModel.types(["type a", 'type b', 'type c'])
}, 1000);
//$.getJSON('json/stateArray.json', function(jStates){
setTimeout(function() {
viewModel.states(["state d", 'state e', 'state f'])
}, 2000);
// ever more - update types again in 5 sec
//$.getJSON('json/typeArray.json', function(jTypes){
setTimeout(function() {
viewModel.types(["type g", 'type h', 'type i', 'type j'])
}, 5000);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div>States:</div>
<!-- ko if: states().length === 0 -->
<div>There are no states for a while...</div>
<!-- /ko -->
<!-- ko foreach: states -->
<div data-bind="text: $data"></div>
<!-- /ko -->
<div>Types:</div>
<!-- ko if: types().length === 0 -->
<div>There are no types for a while...</div>
<!-- /ko -->
<!-- ko foreach: types -->
<div data-bind="text: $data"></div>
<!-- /ko -->
答案 1 :(得分:0)
请注意,在这个答案中,我明确地重新发明了轮子,以显示这是如何工作的基本概念。有些库,包括你似乎已经使用过的库(jQuery),它使这项任务变得更加容易和流畅。
基本上,您希望运行ko.applyBindings
,但仅在完成两个单独的异步请求之后。这是一种模式:
var viewModel = new MyViewModel();
function tryApplyBindings() {
if (viewModel.types().length > 0 &&
viewModel.states().length > 0) {
ko.applyBindings(viewModel);
}
}
$(function () {
$.getJSON('json/typeArray.json', function(jTypes){
console.log("Setting types in viewModel: " + viewModel.name);
viewModel.types = jTypes;
tryApplyBindings();
});
$.getJSON('json/stateArray.json', function(jStates){
console.log("Setting states in viewModel: " + viewModel.name);
viewModel.loadStates(jStates);
tryApplyBindings();
});
});
然而,再次:请注意,这会重新发明轮子。您可以使用jQuery的promise功能(例如,使用this approach)来实现更优雅和DRY的承诺组合。
作为脚注,您还可以考虑直接运行applyBindings
,并创建一个与空数组一样好看的视图。然后,当promises返回时,UI会自动更新。