如何使用Durandal的createChildRouter

时间:2013-11-12 21:53:14

标签: javascript asp.net-mvc-4 durandal hottowel

我整天都在努力弄清楚如何在我的热毛巾(MVC4 SPA)项目中使用Durandal正确创建一个子路由器。这就是我现在所拥有的:

shell.js

var routes = [
    { route: '', moduleId: 'home', title: 'Home', nav: 1 },
    { route: 'inventory/index', moduleId: 'inventory/inventory', title: 'Inventory', nav: 2 }];
return router.makeRelative({ moduleId: 'viewmodels' }) // router will look here for viewmodels by convention
    .map(routes)            // Map the routes
    .buildNavigationModel() // Finds all nav routes and readies them
    .activate();            // Activate the router

inventory.js

define(['services/logger', 'plugins/router'], function (logger, router) {
    var title = 'Details';
    var childRouter = router.createChildRouter()
      .makeRelative({
         moduleId: 'viewmodels/inventory',
         fromParent: true
      }).map([
            { route: '', moduleId: 'inventory', title: 'Inventory', nav: 3 },
            { route: 'items', moduleId: 'items', title: 'Items', nav: 4 }])
        .buildNavigationModel();
    var vm = {
       router: childRouter,
       activate: activate,
       title: title
    };

    return vm;

    //#region Internal Methods
    function activate() {
       logger.log(title + ' View Activated', null, title, true);
    }
    //#endregion
});

我目前遇到的问题:

  1. 点击清单视图时激活两次
  2. 没有进一步的导航选项变得可见,虽然右上角出现了一些空的3D圆角矩形...我不确定这是一个未能消失的进度条还是一些失败的导航元素。
  3. 我的项目文件组织如下:

    Project file tree structure

1 个答案:

答案 0 :(得分:1)

我的主要问题是,我希望在我的视图或视图模型中没有实现子导航的情况下显示子导航菜单。我不知道儿童导航不是现有导航所固有的。以下是我必须做出的改变。

通过在data-bind添加router.navigationModel的元素来更改我的inventory.html文件以充当子导航容器,该元素会选择并显示导航菜单;还包括data-bindrouter的元素,该元素将在最低导航级别获取叶节点(页面内容):

<section>
    <header>
    <h2 class="page-title" data-bind="text: title"></h2>
    <nav class="pull-left">
        <ul class="nav nav-pills nav-stacked" data-bind="foreach: router.navigationModel()">
            <li><a data-bind="    css: { active: isActive }, attr: { href: hash }, text: title" 
            href="#"></a></li>
        </ul>
    </nav>
    </header>
    <section id="inventoryPane" data-bind="router: { transition: 'entrance', cacheViews: true }"></section>
</section>

注意此处完全导航视图中实际涉及3个模块。 shell.js是具有顶级导航的根,然后inventory.js(例如)将是具有子导航按钮的另一个容器,最后items.js(例如)将表示inventory.js容器中显示的内容。 / p>

接下来,我需要更新我的inventory.js作为容器,并在我调用makeRelative时指定模块的完全限定路径(在我的问题中将代码发布为许多绝望的实验之一后我删除了);如果你没有得到moduleId,那么在尝试访问不存在的对象的router属性时会发生致命错误,如果你正在运行IE,调试器给出的消息根本没有用:

define(['services/logger', 'plugins/router'], function (logger, router) {
   var title = 'Inventory';
   var childRouter = router.createChildRouter()
   .makeRelative({
      moduleId: 'viewmodels/inventory',
      fromParent: true
   }).map([
         { route: 'items', moduleId: 'items', title: 'Items', nav: 3 }])
      .buildNavigationModel();
   var vm = {
      router: childRouter,
      activate: activate,
      title: title
   };

   return vm;

   //#region Internal Methods
   function activate() {
      logger.log(title + ' View Activated', null, title, true);
   }
   //#endregion
});

接下来,似乎我必须更新我的根级别路由上的哈希值,以避免错误地找不到“* inventory”路由。我不知道为什么splat路线不能自动更好地处理我;不知何故淘汰样本解决了这个问题,但我不能没有覆盖哈希:

var routes = [
    { route: '', moduleId: 'home', title: 'Home', nav: 1 },
    { route: 'inventory*inventory', moduleId: 'inventory', title: 'Inventory', hash:"#inventory", nav: 2 }];

最后,我不得不重组我的树,将库存文件上移一级:

Project tree structure