ОК, поэтому этот ответ в основном является модификацией previous routing answer, позволяя на этот раз несколько уровней (вопрос о трех уровнях, но я дам общий ответ для любого количества уровней).
Модель
Как и в моем предыдущем ответе, я не буду использовать дочерние маршрутизаторы Дюрандаль (причины, указанные в описании сцепленных ранее ответа). Вместо этого будет предоставлен мой собственный способ определения «встроенных» маршрутов.
Давайте предположим, имеющие следующие моделями
var model = [
{
route: '',
moduleId: 'viewmodels/home',
title: 'Validation test',
nav: true,
hash: ''
},
{
route: 'samples',
moduleId: 'viewmodels/samples',
moduleRootId: 'viewmodels', // Custom property to make child routes easier
title: 'Samples',
nav: true,
hash: 'samples',
childRoutes: [
{ route: 'simpleList', moduleId: 'simpleList', title: 'SimpleList', nav: true, hash : 'simpleList', childRoutes: [
{ route: 'simpleListA', moduleId: 'simpleListA', title: 'SimpleListA', nav: true, hash : 'simpleListA' },
{ route: 'simpleListB', moduleId: 'simpleListB', title: 'SimpleListB', nav: true, hash : 'simpleListB' } ] },
{ route: 'clickCounter', moduleId: 'clickCounter', title: 'Click Counter', nav: true, hash : 'clickCounter' }
]
}
];
У нас есть два 0-уровня (верхний уровень) маршрутов (Home и образцы), два 1-уровня (Чайлдс выборки - SimpleList и ClickCounter) и два 2- уровень (дочерние элементы SimpleList - SimpleListA и SimpleListB).
Трансформация
Что Durandal ожидает, чтобы это просто список маршрутов. Поэтому нам нужно преобразовать нашу красивую структуру модели в список маршрутов (с некоторыми изменениями в hash, moduleId [Я предполагаю, что структура папки viewModel такая же, как и наши маршруты, т. Е. Модели просмотра SimpleList и ClickCounter находятся в подпапках, то же самое для SimpleListA и SimpleListB])
Алгоритм - это в основном траверс и выравнивание дерева.
function flatRoutes (routes, level, path, parent) {
var output = []
$.each(routes, function(index, route) {
route.route = path + route.route;
route.moduleId = path + route.moduleId;
route.hash = '#' + path + route.hash;
route.parent = parent;
route.level = level;
output = output.concat(route)
if (route.childRoutes !== undefined) output = output.concat(flatRoutes(route.childRoutes, level + 1, route.route + '/', route.route))
})
return output;
}
function createRoutes (routes) {
return flatRoutes(routes, 0, '', '')
}
Как всегда маршруты должны быть зарегистрированы и маршрутизатор активирован:
var routes = createRoutes(model);
return router.map(routes)
.buildNavigationModel()
.activate();
Rendering
К сожалению, эта часть не проверяется, как я не использую Дюрандаль/стек Нокаут больше.
В ShellVM (или где-то еще вы хотите связать маршрутизатор с нокаутом) вам понадобится функция поиска дочерних маршрутов для данного родителя.
function findRoutes (parent) {
var output = []
$.each(router.navigationModel, function(index, route) {
if(route.paent === parent) output = output.concat(route)
}
return output;
}
А в разделе «Нокаут/HTML» вам нужно будет использовать рекурсивные шаблоны для нокаута.
<script id="treeElement" type="text/html">
<li>
<span data-bind="text: title"></span>
<ul data-bind="template: { name: 'treeElement', foreach: $root.vm.findRoutes($data.moduleId) }">
</ul>
</li>
</script>
<ul data-bind="template: { name: 'treeElement', foreach: $root.vm.findRoutes('') }"></ul>
Конечно, это просто оказывающего маршрутизатор в качестве простого списка mulitlevel - Вам нужно будет изменить его в соответствии с тем, что вы хотите достичь, и какие CSS рамки вы используете. Но это должно быть легко.
Извините, но вы можете дать мне пример проекта? У меня много ошибок в проекте. Значение привязки: template: {name: 'treeElement', foreach: $ root.vm.findRoutes ('')} Возможно, вы можете указать URL-адрес в GitHub или аналогичном сервере? Невозможно проанализировать привязки. Сообщение: $ root.vm не определено; –