Как использовать createChildRouter Дюрандаля

Я боролся весь день, не в силах понять, как правильно создать дочерний маршрутизатор с помощью Durandal в моем проекте на основе горячего полотенца (MVC4 SPA). Вот что у меня есть на данный момент:

оболочка.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

инвентарь.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. Дальнейшие параметры навигации не отображаются, хотя в правом верхнем углу появляется пустой трехмерный прямоугольник со скругленными углами ... Я не уверен, что это индикатор выполнения, который не исчез, или какой-то неисправный элемент навигации.

Мои файлы проекта организованы следующим образом:

Древовидная структура файлов проекта


person BlueMonkMN    schedule 12.11.2013    source источник
comment
Проверьте, имеет ли значение изменение явного маршрута inventory/index на splat-маршрут inventory/index/*whatever в shell.js. См. durandaljs.com/documentation/Using-The-Router.   -  person RainerAtSpirit    schedule 13.11.2013
comment
@RainerAtSpirit Это устраняет дополнительную активацию просмотра сведений, но журнал консоли затем сообщает LOG: Route '*whatever' Not Found (я изменил код сообщения об ошибке на system.log('Route \'' + coreFragment + '\' Not Found');, чтобы иметь некоторое представление о том, что происходит).   -  person BlueMonkMN    schedule 13.11.2013
comment
Просто к вашему сведению, 3D-прямоугольник - это место, где вы удалили шрифт awesome, но не объект счетчика, показывающий изменения навигации в оболочке.   -  person PW Kad    schedule 13.11.2013


Ответы (1)


Моя основная проблема заключалась в том, что я ожидал появления дочерних меню навигации без реализации дочерней навигации в моем представлении или модели представления. Я не знал, что дочерняя навигация не является неотъемлемой частью существующей навигации. Вот какие изменения мне пришлось сделать.

Измените мой файл inventory.html, чтобы он действовал как дочерний контейнер навигации, добавив элемент с data-bind на router.navigationModel, который берет и отображает дочернее меню навигации; также включите элемент с data-bind на router, который подберет конечный узел (содержимое страницы) на самом низком уровне навигации:

<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.

Затем мне нужно было обновить свой inventory.js, чтобы он действовал как контейнер, и указать полный путь для модуля в моем вызове makeRelative (который я удалил после публикации кода в своем вопросе в качестве одного из многих отчаянных экспериментов); если вы не получите правильный moduleId, возникнут фатальные ошибки при попытке доступа к свойству маршрутизатора несуществующего объекта, а сообщение, выдаваемое отладчиком, совершенно бесполезно, если вы используете 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 }];

И, наконец, мне пришлось реструктурировать мое дерево, чтобы переместить файлы инвентаризации на один уровень выше:

Древовидная структура проекта

person BlueMonkMN    schedule 13.11.2013