在Knockout.js中,当你的ViewModel变得非常大时,有不同的方法可以分成多个ViewModel,拥有一些较小的ViewModel而不是一个大的ViewModel总是一个好主意。我使用以下方法,并不确定是否有任何其他更好的方法来做到这一点。注意我使用require.js来定义我的ViewModel,但为了简单起见,我不在下面的示例中包含该代码。在下面的例子中,假设我在一个屏幕上工作,你可以编辑学生注册的课程。最初我在StudentViewModel中有所有与课程相关的功能(如添加/编辑/删除课程)。但我决定将它们移到CourseViewModel,然后在StudentViewModel中引用CourseViewModel。请注意,在创建CourseViewModel时,我传递了对student.courses可观察数组的引用。这是一个为View提供小视图模型的好方法,还是有更好的方法可以做到这一点?
function Course(data) {
data = data || {};
this.id = ko.observable(data.id);
this.name = ko.observable(data.name);
}
function Student(data) {
data = data || {};
this.id = ko.observable(data.id);
this.firstName = ko.observable(data.firstName);
this.courses = ko.observableArray($.map(data.courses, function (item) { return new Course(item); }));
}
function CourseViewModel(studentid, courses) {
var self = this;
// please note below is a reference to courses observable function
self.courses = courses;
this.addCourse = this.addCourse.bind(this);
this.editCourse = this.editCourse.bind(this);
this.removeCourse = this.removeCourse.bind(this);
}
ko.utils.extend(CourseViewModel.prototype, {
addCourse: function(course) {
var self = this;
self.courses.push(course);
},
editCourse: function(course) {
var self = this;
// find the course and update it
},
removeCourse: function(course) {
var self = this;
self.courses.remove(course);
}
});
// main ViewModel which will be used for binding
function StudentViewModel(id) {
var self = this;
self.id = ko.observable(id);
self.student = ko.observable();
self.courseViewModel = ko.observable();
// retrieve student object from server
(function() {
var data = dataService.getStudent(id);
self.student(new Student(data));
// please note below I am passing a reference to courses observable function
self.courseViewModel(new CourseViewModel(id, student.courses));
)();
}
// binding
ko.applyBindings(new StudentViewModel(5));
答案 0 :(得分:2)
我这样做的方法是维护主视图模型(big fat viewmodel)并在其中定义子视图模型。
e.g。
var MasterVM = {
subVM1 : SubViewModel1(),
subVM2: SubViewModel2()
};
您可以使用主视图模型应用绑定,并随时随地使用子视图模型实例。
我尝试了不同的技术但显然失败了。这是我从KnockoutJS转移到DurandalJS的唯一原因。模块化编程非常有效,无需担心多个视图模型。
多个不同视图模型之间的另一种通信方法是在代码中引入 Pub-Sub 。有一个非常好的插件由Ryan Niemeyer称为KO Postbox(https://github.com/rniemeyer/knockout-postbox)
我发现它们在不同场景中都很有用。我会采用第一种方法。
在多个视图模型之间共享模型:
//Shared Models for both the ViewModels
var profileModel = function(vm){
var self = this;
self.first = ko.observable("Bob");
self.last = ko.observable("Smith");
self.vm = ko.observable(vm);
};
var officeModel = function(vm){
var self = this;
self.header = ko.observable("Administration");
self.vm = ko.observable(vm);
};
var viewModel1 = function(){
var self = this;
self.profileModel = new profileModel("Called from viewModel1");
self.officeModel = new officeModel("office model Called from viewModel1");
};
var viewModel2 = function(){
var self = this;
self.profileModel = new profileModel("Called from viewModel2");
self.officeModel = new officeModel("office model Called from viewModel2");
};
//the overall view model
var viewModel = function(){
var self = this;
self.profile = new profileModel(),
self.office = new officeModel(),
self.viewModel1 = new viewModel1(),
self.viewModel2 = new viewModel2()
};
ko.applyBindings(new viewModel());