Мне нужно создать многоуровневое меню навигации. Содержимое меню зависит от пользователя. Я планирую вытащить коллекцию элементов навигации, которая может содержать массив дочерних элементов через службу, которая вернет данные как JSON. Каждый пример навигации/маршрутизации, который я видел, использует статические маршруты или одноуровневые меню. Я немного читал о маршрутизации детей, но, похоже, это не то, что мне нужно. Единственное, что я могу придумать, это создать пользовательский элемент навигации, модель которого будет регистрировать маршруты в простом массиве, используя данные в коллекции навигационных элементов. Затем я использовал бы эту коллекцию для рендеринга HTML вместо использования маршрутизатора, поскольку он содержит иерархическую информацию. Есть ли более простой способ сделать это. Это первая структура JS, с которой я работал, поэтому я стараюсь ускориться.Aurelia: простой способ создать вложенное/многоуровневое меню навигации
ответ
Это довольно просто, на самом деле. Вы просто добавите свойство к объекту 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
в примере ниже), чтобы перейти к правильному маршруту на дочернем маршрутизаторе. Вы действительно можете делать все, что хотите, поскольку вы можете поместить любую старую вещь, которая вам нужна на этом объекте настроек.
я решил подобную проблему следующим образом:
- Я просто дерево навигации получены с сервера
- Тогда я иду по дереву и преобразовать все элементы навигации для Аурелия маршрутов, на самом деле сглаживаются дерево в массив, так что каждый маршрут будет иметь настройки свойства, как:
{id: 2, parentId: 1, level: 1}
в тот момент - Тогда я прохожу этот плоский массив
config.map()
и создать новый объект дерева с использованием элементов изrouter.navigation
(помните: я спасid
иparentId
вsettings
) наrouter.ensureConfigured().then(_ => {createNavTree(router.navigation)})
- Используйте вывод из
createNavTree(...)
, чтобы отобразить элементы списка.(level
используется только для некоторого стайлинга) - Так что в целом я создаю плоский
router.navigation
массив и использовать его элементы, чтобы создать собственную структуру дерева, чтобы сделать навигацию
Также я слушаю изменения в router.currentInstruction
для отслеживания меню рушится когда подэлемент перемещается с использованием впрыскиваемого ObserverLocator
.
`import {ObserverLocator} from 'aurelia-framework';`
...
this.routerCurrentInstructionSub = this.observerLocator
.getObserver(router, 'currentInstruction')
.subscribe((newValue, oldValue) => { ... });
Обратите внимание, что подписка должна быть выпущена, когда не требуется, чтобы избежать утечек памяти this.routerCurrentInstructionSub.dispose();
Основное преимущество этого решения - это то, что вы получаете полнофункциональные маршруты, поэтому вы можете сделать дерево подразделов как активное время навигационное.
Также он не ограничивает использование вспомогательных маршрутизаторов для подпунктов.
Вместо того, чтобы настраивать наблюдателя объекта, вы можете подписаться на событие маршрутизатора с помощью агрегатора событий. Проверьте https://ilikekillnerds.com/2015/09/understanding-aurelia-router-events/ –
@AshleyGrant моя проблема в том, что я не смог поймать события дочерних маршрутизаторов, возможно, это уже исправлено, но 'ObjectObserver' тоже отлично работает – valichek
А, это имеет смысл –