【发布时间】:2015-08-25 19:41:40
【问题描述】:
我正在尝试制作多级菜单。菜单应同时包含一级,在某些部分为二级和三级。部分不能连续放置。示例菜单:
我写信给 Google 的团队 DurandalJS,但没有人解释我做错了什么。我找到了这个example,但我不工作。
呼吁了解此类事情的人: 1.我应该如何组织这个菜单的逻辑。 2.如何将数据绑定到视图 3. 我需要为此使用 ChildRouter 吗?
希望能得到帮助。
【问题讨论】:
标签: durandal
我正在尝试制作多级菜单。菜单应同时包含一级,在某些部分为二级和三级。部分不能连续放置。示例菜单:
我写信给 Google 的团队 DurandalJS,但没有人解释我做错了什么。我找到了这个example,但我不工作。
呼吁了解此类事情的人: 1.我应该如何组织这个菜单的逻辑。 2.如何将数据绑定到视图 3. 我需要为此使用 ChildRouter 吗?
希望能得到帮助。
【问题讨论】:
标签: durandal
好的,所以这个答案基本上是对previous routing answer 的修改,允许这个时间多个级别(问题大约是 3 个级别,但我会提供任何级别的一般答案)。
型号
与我之前的答案一样,我不会使用 Durandal 子路由器(原因在链接的早期答案的描述中说明)。而是提供我自己定义“嵌入式”路由的方式。
假设有以下模型
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 和 Samples)、两个 1 级(Sample 的子级 - 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();
渲染
抱歉,这部分没有经过测试,因为我不再使用 Durandal / Knockout 堆栈。
在 ShellVM(或您想将路由器与 Knockout 绑定的其他地方)中,您将需要为给定父级查找子路由的函数。
function findRoutes (parent) {
var output = []
$.each(router.navigationModel, function(index, route) {
if(route.paent === parent) output = output.concat(route)
}
return output;
}
并且在 Knockout / HTML 部分中,您将需要使用递归模板进行 Knockout。
<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>
当然,它只是将路由器渲染为简单的多级列表 - 您需要根据您想要实现的目标以及您使用的 CSS 框架来更改它。但这应该很容易。
【讨论】: