Javascript Knockoutjs中的子视图模型

Javascript Knockoutjs中的子视图模型,javascript,knockout.js,Javascript,Knockout.js,认识得好 我正在玩Knockoutjs,目标是拥有一个ViewModel,它控制多个子ViewModel。这样做是为了更好地控制视图本身,并防止将视图的各个部分放到自己的小地方。下面的代码应该解释我的想法: ApplicationViewModel ApplicationViewModel = function () { var self = this; // Context (for laziness' sake, no separate VM) self.activeProject = k

认识得好

我正在玩Knockoutjs,目标是拥有一个ViewModel,它控制多个子ViewModel。这样做是为了更好地控制视图本身,并防止将视图的各个部分放到自己的小地方。下面的代码应该解释我的想法:

ApplicationViewModel

ApplicationViewModel = function () {
var self = this;

// Context (for laziness' sake, no separate VM)
self.activeProject = ko.observable();

// States
self.projectsLoaded = ko.observable(false);

// State-change events
// Let application know that loading of projects has been called
self.projectsLoaded.subscribe(function (newValue) {
    if (newValue === true) {
        console.log('Projects have loaded');
    } else {
        console.log('Projects have not loaded');
    }
});
// Let application know that selection of a project has happened
self.activeProject.subscribe(function (newValue) {
    if (newValue != null) {
        // Notify other viewmodels that a project has been (successfully loaded)
        // Use hook-pattern to hook into this event
    } else {
        // Notify something went wrong- present user with a notification
        // Application stops processes that are project-dependant
    }
});

self.ProjectViewModel = new ProjectViewModel();
};
ProjectViewModel = function () {
var self = this;

self.projects = ko.observableArray();

self.loadProjects = function () {
    // Business logic to retrieve projects, think AJAX
    var placeHolderProjects = [];

    // Find projects somewhere and load them up!

    // If something went wrong, notify parent
    if (placeHolderProjects.length > 0) {
        self.projects(placeHolderProjects);
        $root.projectsLoaded(true);
    } else {
        $root.projectsLoaded(false);
    }
};

self.selectProject = function (projectId) {
    if (!projectId) {
        $.parent.activeProject = null;
        return;
    }

    // Fetch data for project, stuff like membershipId
    var loadProjectResult = magicalLoadFunction(projectId);

    if (loadProjectsResult === true) {
        $root.activeProject(projectId);
    } else {
        $root.activeProject(projectId);
    }

    // Exit
    return;
}

/********** Constructor logic
****************************/
self.loadProjects();
};
项目视图模型

ApplicationViewModel = function () {
var self = this;

// Context (for laziness' sake, no separate VM)
self.activeProject = ko.observable();

// States
self.projectsLoaded = ko.observable(false);

// State-change events
// Let application know that loading of projects has been called
self.projectsLoaded.subscribe(function (newValue) {
    if (newValue === true) {
        console.log('Projects have loaded');
    } else {
        console.log('Projects have not loaded');
    }
});
// Let application know that selection of a project has happened
self.activeProject.subscribe(function (newValue) {
    if (newValue != null) {
        // Notify other viewmodels that a project has been (successfully loaded)
        // Use hook-pattern to hook into this event
    } else {
        // Notify something went wrong- present user with a notification
        // Application stops processes that are project-dependant
    }
});

self.ProjectViewModel = new ProjectViewModel();
};
ProjectViewModel = function () {
var self = this;

self.projects = ko.observableArray();

self.loadProjects = function () {
    // Business logic to retrieve projects, think AJAX
    var placeHolderProjects = [];

    // Find projects somewhere and load them up!

    // If something went wrong, notify parent
    if (placeHolderProjects.length > 0) {
        self.projects(placeHolderProjects);
        $root.projectsLoaded(true);
    } else {
        $root.projectsLoaded(false);
    }
};

self.selectProject = function (projectId) {
    if (!projectId) {
        $.parent.activeProject = null;
        return;
    }

    // Fetch data for project, stuff like membershipId
    var loadProjectResult = magicalLoadFunction(projectId);

    if (loadProjectsResult === true) {
        $root.activeProject(projectId);
    } else {
        $root.activeProject(projectId);
    }

    // Exit
    return;
}

/********** Constructor logic
****************************/
self.loadProjects();
};
因此,基本上,我要寻找的是: -从viewmodels中各自的子/父属性控制父/子属性

我也在研究AngularJS,但我真的想先让它在KnockoutJS中工作:)直接的问题是,我无法让$root/$parent工作。我将ApplicationViewModel绑定到$(document).ready()处理程序中,不确定是否还必须将子viewmodels绑定到视图。我已将ApplicationViewModel绑定到body元素


感谢您的阅读,可能还有您的回答/帮助我上路:)

由@jansommer提供的答案证明是成功的

我更改了以下行(将其作为参数添加):

这就是我们所需要的


谢谢

您的ProjectViewModel可以接受一个参数,例如“parent”,当您从ApplicationViewModel实例化它时,您可以使用
self.ProjectViewModel=new ProjectViewModel(this)
进行实例化。但是最好让您的子视图模型公开父视图可以使用的函数或观察对象,这样子视图模型就不必知道它的父视图。这通常会使代码更清晰,但您的用例可能会有所不同。@JanSommer:谢谢您的建议,我正在尝试。至于公开函数/可观察对象,在我的这个测试用例之前,我通常是这样做的。