2017-01-10 8 views
3

Мне нужно создать многоуровневое меню навигации. Содержимое меню зависит от пользователя. Я планирую вытащить коллекцию элементов навигации, которая может содержать массив дочерних элементов через службу, которая вернет данные как JSON. Каждый пример навигации/маршрутизации, который я видел, использует статические маршруты или одноуровневые меню. Я немного читал о маршрутизации детей, но, похоже, это не то, что мне нужно. Единственное, что я могу придумать, это создать пользовательский элемент навигации, модель которого будет регистрировать маршруты в простом массиве, используя данные в коллекции навигационных элементов. Затем я использовал бы эту коллекцию для рендеринга HTML вместо использования маршрутизатора, поскольку он содержит иерархическую информацию. Есть ли более простой способ сделать это. Это первая структура JS, с которой я работал, поэтому я стараюсь ускориться.Aurelia: простой способ создать вложенное/многоуровневое меню навигации

ответ

3

Это довольно просто, на самом деле. Вы просто добавите свойство к объекту settings маршрута. Вы можете назвать все, что захотите. Он будет иметь набор пунктов меню для подменю. Просто используйте это для создания подменю.

Вот пример: https://gist.run?id=beb5ba9155fdb2ccefcf78676879b1ca

app.html

<template> 
    <ul> 
    <li repeat.for="row of router.navigation" class="${row.isActive ? 'active' : ''}"> 
     <a href.bind="row.href">${row.title}</a> 
     <ul> 
     <li repeat.for="sub of row.settings.subRoutes"> 
      <a route-href="route.bind: row.config.name; params.bind: sub.params">${sub.name}</a> 
     </li> 
     </ul> 
    </li> 
    </ul> 

    <div class="page-host"> 
    <router-view></router-view> 
    </div> 
</template> 

app.js

import {activationStrategy} from 'aurelia-router'; 

export class App { 
    configureRouter(config, router) { 
    config.title = 'Aurelia'; 
    config.map([ 
     { 
     route: ['', 'one'], 
     name: 'one',  
     moduleId: 'one',  
     nav: true, 
     title: 'Page 1', 
     activationStrategy: activationStrategy.invokeLifecycle, 
     settings: { 
      subRoutes: [ 
      { 
       name: 'Sub-choice 1', 
       params: { 
       'foo': 'bar' 
       } 
      }, 
      { 
       name: 'Sub-choice 2', 
       params: { 
       'foo': 'two' 
       } 
      } 
      ] 
     } 
     }, 
     { route: 'two',   name: 'two',  moduleId: 'two',  nav: true, title: 'Page 2' } 
    ]); 

    this.router = router; 
    } 
} 

one.html

<template> 
    Page One<br /> 
    Params:<br /> 
    <pre><code>${params}</code></pre> 
</template> 

one.js

export class One { 
    activate(params) { 
    this.params = JSON.stringify(params); 
    } 
} 

Параметры вы передаете может быть все что угодно. Например, они могут быть информацией о том, какой маршрут должен быть активирован на дочернем маршрутизаторе на маршруте, который вы собираетесь использовать. Вы можете вызвать router.navigate... в методе активации страницы (one.js в примере ниже), чтобы перейти к правильному маршруту на дочернем маршрутизаторе. Вы действительно можете делать все, что хотите, поскольку вы можете поместить любую старую вещь, которая вам нужна на этом объекте настроек.

1

я решил подобную проблему следующим образом:

  1. Я просто дерево навигации получены с сервера
  2. Тогда я иду по дереву и преобразовать все элементы навигации для Аурелия маршрутов, на самом деле сглаживаются дерево в массив, так что каждый маршрут будет иметь настройки свойства, как: {id: 2, parentId: 1, level: 1} в тот момент
  3. Тогда я прохожу этот плоский массив config.map() и создать новый объект дерева с использованием элементов из router.navigation (помните: я спас id и parentId в settings) на router.ensureConfigured().then(_ => {createNavTree(router.navigation)})
  4. Используйте вывод из createNavTree(...), чтобы отобразить элементы списка.(level используется только для некоторого стайлинга)
  5. Так что в целом я создаю плоский router.navigation массив и использовать его элементы, чтобы создать собственную структуру дерева, чтобы сделать навигацию

Также я слушаю изменения в router.currentInstruction для отслеживания меню рушится когда подэлемент перемещается с использованием впрыскиваемого ObserverLocator.

`import {ObserverLocator} from 'aurelia-framework';` 
... 
this.routerCurrentInstructionSub = this.observerLocator 
    .getObserver(router, 'currentInstruction') 
    .subscribe((newValue, oldValue) => { ... }); 

Обратите внимание, что подписка должна быть выпущена, когда не требуется, чтобы избежать утечек памяти this.routerCurrentInstructionSub.dispose();

Основное преимущество этого решения - это то, что вы получаете полнофункциональные маршруты, поэтому вы можете сделать дерево подразделов как активное время навигационное.

Также он не ограничивает использование вспомогательных маршрутизаторов для подпунктов.

+0

Вместо того, чтобы настраивать наблюдателя объекта, вы можете подписаться на событие маршрутизатора с помощью агрегатора событий. Проверьте https://ilikekillnerds.com/2015/09/understanding-aurelia-router-events/ –

+0

@AshleyGrant моя проблема в том, что я не смог поймать события дочерних маршрутизаторов, возможно, это уже исправлено, но 'ObjectObserver' тоже отлично работает – valichek

+0

А, это имеет смысл –