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

时间:2015-08-06 12:13:08

标签: knockout.js knockout-3.0

我目前正在开发一个测试网络应用来测试Knockout的组件功能。我使用RequireJS来加载组件。虽然我能够这样做,但我被困在一些地区,有些地方,我不确定我做的是不是正确的事。

该应用程序包含一个带标题的页面,左侧栏和右侧剩余空间的内容区域。这3个都注册为组件。左侧栏用作导航,并具有无序列表,其中列表项通过执行AJAX调用来填充。单击列表项时,右侧的内容应显示与单击的列表项对应的组件/视图。

有了这些,这是我的问题:

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

  2. 我不知道如何正确地传达侧栏中的点击以显示右侧的内容。我怎么能以最小的依赖关系来做这件事,或者我该怎么做呢?

  3. 具有视图模型的父组件是否可以在其模板中具有子组件,但该子组件是否可以从父视图模型获取其数据?如果是的话,该怎么做?

  4. 这些问题让我几天都在阅读,但仍无法让它工作或仍然感到困惑。如果您只对单个项目有答案,请随时发布。希望所有人都能得到答案。

    编辑(源代码)

    标题:

    模板

    <div>
    </div>
    

    VM

    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>
    

    VM

        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>
    

    VM

    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>
    

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

1 个答案:

答案 0 :(得分:0)

我认为最能帮助您的功能是using params in the components。我开始使用您的示例代码,但它太复杂,无法做出简单的工作示例。但您的父HTML可能如下所示:

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

其中chosen是主视图模型中的一个observable。您的nav viewmodel构造函数可能会以

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

所以现在导航视图模型的lastClicked成员与来自父视图的chosen具有相同的可观察性。这是您可以将observable分享到组件的方式。例如,您可以将nav组件写入其中,并从中读取内容组件(以设置其内容)。他们都不知道对方,他们只是知道他们已被赋予可观察性以用于某个目的。

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