使用Knockout组件的一些问题(使用RequireJS加载)

Some questions working with Knockout components (using RequireJS for loading)

我目前正在开发一个测试网络应用程序来测试 Knockout 的组件功能。我使用 RequireJS 来加载组件。虽然我能够这样做,但我在某些地方卡住了,而在某些地方,我不确定我是否做对了。

该应用程序包含一个带有 header 的页面、一个左侧边栏,以及 space 上的内容区域保留在右侧。这3个都注册为组件。左侧栏用作导航并有一个无序列表,其中列表项通过执行 AJAX 调用来填充。单击列表项时,右侧的内容应显示与单击的列表项对应的component/view。

有了这些,我的问题是:

  1. 我只能加载实际组件中左侧栏的项目。这个可以吗?我的意思是,当加载左侧栏组件时,它会执行 AJAX 调用,然后在其视图模型上加载数据。我这样做是因为这是我唯一能想到的将数据加载到视图模型的方法。实际上,我更喜欢在应用程序启动时加载数据,然后在侧边栏加载时将数据放入其中。所以我的问题是:我采用的方法是否可行,是否可以采用我喜欢的方法?如果是,怎么办?

  2. 我不知道如何正确传达侧边栏中的点击以显示右侧的内容。我怎样才能做到这一点相互依赖最少,或者我怎样才能做到这一点?

  3. 带有视图模型的 parent 组件是否可以在其模板中包含 child 组件,但 child 组件从 parent 查看模型?如果可以,怎么做?

这些问题让我阅读了好几天,但仍然无法正常工作或仍然感到困惑。如果您只有一个项目的答案,请不要犹豫post。希望所有问题都能得到答复。

编辑(源代码)

为header:

模板

<div>
</div>

虚拟机

define(["text!./admin-main-header.html"], function(template) {

    function AdminMainHeaderViewModel() {
    }

    return { viewModel: AdminMainHeaderViewModel, template: template };
});

对于边栏:

模板

    <div class="vmsc" data-bind="with: adminModules, vertMenu: adminModules">
    <ul data-bind="foreach: modules">
        <li class="has-sub"><a href="javascript:void(0);"><span data-bind="text: name"></span></a>
            <ul data-bind="foreach: $data.submodules">
                <li><a href="javascript:void(0);"><span data-bind="text: name"></span></a></li>
            </ul>
        </li>
    </ul>
</div>

虚拟机

    define(["jquery", "knockout", "ko-mapping", 
    "jquery-vertmenusc", "text!./vert-menu.html"], function($, ko, komap, vmsc, template) {

    ko.mapping = komap;

    function VertMenuScViewModel() {        
        var self = this;
        self.adminModules = ko.observable();

        $.get("http://localhost:8080/_mock_data/admin-modules.txt", function(data) { 
            self.adminModules(ko.mapping.fromJSON(data));
        });
    }

    return { viewModel: VertMenuScViewModel, template: template };
});

对应内容:

模板

<div>
</div>

虚拟机

define(["text!./admin-main-content.html"], function(template) {

    function AdminMainContentViewModel() {
    }

    return { viewModel: AdminMainContentViewModel, template: template };
});

主要HTML:

    <!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <title>Sample</title>               

    <!-- Scripts -->
    <script src="js/require.min.2.1.20.js" data-main="js/app/require.config.js"></script>
</head>

<body>
    <div>

        <admin-main-header></admin-main-header>

        <div>       
            <admin-main-nav></admin-main-nav>
            <admin-main-content></admin-main-content>
        </div>

    </div>
</body>
</html>

内容中还没有代码,因为我不知道应该如何传递数据。我希望这些附加信息能有所帮助。谢谢。

我认为对您帮助最大的功能是 using params in the components。我开始使用您的示例代码,但它太复杂了,无法制作一个简单的工作示例。但是你的 parent HTML 可能看起来像这样:

  <div>
    <admin-main-nav params='lastClicked:chosen'></admin-main-nav>
    <admin-main-content params='toDisplay:chosen'></admin-main-content>
  </div>

其中 chosen 是您主视图模型中的可观察对象。您的导航视图模型构造函数可能以类似

的内容开始
function VertMenuScViewModel(params) {
  var self = this;
  self.adminModules = ko.observable();
  self.lastClicked = params.lastClicked;

所以现在导航视图模型的 lastClicked 成员与 parent 中的 chosen 是相同的可观察对象。这就是您可以将可观察对象共享到组件的方式。例如,您可以让 nav 组件写入它,而 content 组件从中读取(以设置其内容)。他们都不了解对方,他们只知道他们被赋予了一个可观察的对象以用于某个目的。

这也是您在主视图模型中加载数据并将其传递给导航组件的方法。