我认为我提出问题的方式误导了你,所以我做了一个重大的编辑。 我将使用来自knockoutjs教程的代码
“加载和保存数据”,第3步
我做了一个改变来表明我的意思。
function Task(data) {
this.title = ko.observable(data.title);
this.isDone = ko.observable(data.isDone);
}
function TaskListViewModel() {
// Data
var self = this;
self.tasks = ko.observableArray([]);
self.newTaskText = ko.observable();
self.incompleteTasks = ko.computed(function() {
return ko.utils.arrayFilter(self.tasks(), function(task) { return !task.isDone() });
});
// Operations
self.addTask = function() {
self.tasks.push(new Task({ title: this.newTaskText() }));
self.newTaskText("");
};
self.removeTask = function(task) { self.tasks.remove(task) };
// ** Read this!!
// This below is the original code in the tutorial, used to fetch remote data.
// I commented this out, and i will use the below load() method instead.
// **
//$.getJSON("/tasks", function(allData) {
// var mappedTasks = $.map(allData, function(item) { return new Task(item) });
// self.tasks(mappedTasks);
//});
// This is the load method to emulate the above commented
// $.get. Please, DO NOT CARE about the implementation, or
// the setTimeout usage, etc., this method ONLY EXISTS TO
// EMULATE A SLOW SERVER RESPONSE.
// So, we have to ways of using it:
// - load('slow'), will set result after 1 second
// - any other argument will set result instantly.
self.load = function(howFast) {
if (howFast == 'slow') {
setTimeout(function(){
mappedTasks = [];
mappedTasks.push(new Task({
title: 'Some task slowly loaded from server',
isDone: false
}));
}, 1000);
} else {
mappedTasks = [];
mappedTasks.push(new Task({
title: 'Some task quick!',
isDone: false
}));
}
}
// Now please note this:
// - if i use load(), mappedTask is instant updated and
// everything runs fine
// - if i use load('slow'), mappedTask is updated AFTER
// VALUES ARE BOUND, so if you open your browser console
// you will see an "Uncaught ReferenceError: mappedTasks is not defined" error.
self.load();
self.tasks(mappedTasks);
}
ko.applyBindings(new TaskListViewModel());
问题:ViewModel使用 AFTER 进行初始化,因此会导致错误。我想我在代码评论中提供了足够的细节,问我是否认为你需要更多。无论如何,我很惊讶以前没有人打过这个东西,所以我错过了一些非常重要的东西吗?
问题:如何避免这种情况?
答案 0 :(得分:0)
你有一个HTML错误。
您的setTimeout函数正在尝试以编程方式将所选选项设置为不在列表中的选项。浏览器无法做到这一点,因此选择保持不变。
function ViewModel() {
// Setup something.
var self = this;
self.foo = ko.observable();
self.options = ko.observableArray([{id:1, name:'Homer'}, {id:2, name:'Barney'}]);
// Make a lot of async data load, like
// $.get('this', function(){ /* Process data */ });
// $.get('that', anotherHandler);
// $.get('somethingElse', self.someObservable);
// Assume the whole process would take 1 second.
setTimeout(function(){
self.options.push({id: 3, name: 'Grimes'});
self.foo(3);
// Too late! foo has been overriden by the select-options binding,
// so this one will not log 'Grimes' as expected.
console.log('Loading done, check foo value:' + self.foo());
}, 1000);
}