Durandal 2.0-用于嵌套菜单的子路由器? [英] Durandal 2.0 - Child routers intended for nested menus?

查看:86
本文介绍了Durandal 2.0-用于嵌套菜单的子路由器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在构建一个应用程序,并希望显示一个两层菜单,并且两层始终可用. Durandal 2.0 推出了他们的新路由器,该路由器支持子路由器",从而可以更容易的深层链接.

I've building an app, and wanting to show a 2-tier menu, with both tiers always available. Durandal 2.0 introduced their new router, which supports 'child routers', which allow for easier deeplinking.

我的问题-我可以永久加载子级"导航路线(当父级处于非活动状态时显示子菜单),还是子级路由器"设计旨在懒惰-一旦评估了深层链接,就加载它们以对其进行评估?

My question - Can I have my 'child' navigation routes permanently loaded (and a sub menu rendered when the parent is not active), or is the 'child router' design intended to lazy-load them to evaluate them once a deeplink is to be evaluated?

Durandal示例显示,主导航注册一条摔跤路线,然后然后加载/激活该视图模型,然后注册子路由器.

The Durandal examples show main navigation register a splat route, then when that view model is loaded/activated, the child router is registered.

例如:在Durandal 2.0随附的示例中,主面在shell.js

E.g.: In the example provided with Durandal 2.0, the mian nev is registered in shell.js

router.map([
                { route: ['', 'home'], moduleId: 'hello/index', title: 'Validation test', nav: true },
                { route: 'knockout-samples*details',    moduleId: 'ko/index',               title: 'Knockout Samples',  nav: true, hash: '#knockout-samples' }
            ]).buildNavigationModel()
              .activate();

然后ko/index.js视图模型注册子对象(在activate()上)

And the ko/index.js view model then registers the children (on activate())

var childRouter = router.createChildRouter()
        .makeRelative({
            moduleId:'ko',
            fromParent:true
        }).map([
            { route: '',                moduleId: 'helloWorld/index',       title: 'Hello World',           type: 'intro' },
            { route: 'helloWorld',      moduleId: 'helloWorld/index',       title: 'Hello World',           type: 'intro',      nav: true},
            { route: 'clickCounter',    moduleId: 'clickCounter/index',     title: 'Click Counter',         type: 'intro',      nav: true}
        ]).buildNavigationModel();

我要在哪里定义路线,例如:

 var routes = [
   { route: ['', 'home'], 
        moduleId: 'hello/index', 
        title: 'Validation test', 
        nav: true },
   { route: 'knockout-samples*details',    
        moduleId: 'ko/index',
        moduleRootId: 'ko', // Custom property to make child routes easier              
        title: 'Knockout Samples',  
        nav: true, 
        hash: '#knockout-samples',
        childRoutes: [
            { route: '',                moduleId: 'helloWorld/index',       title: 'Hello World',           type: 'intro' },
            { route: 'helloWorld',      moduleId: 'helloWorld/index',       title: 'Hello World',           type: 'intro',      nav: true},
            { route: 'clickCounter',    moduleId: 'clickCounter/index',     title: 'Click Counter',         type: 'intro',      nav: true}
        ]}
   ])

我正在努力的部分是注册子路径,并在导航到它们时让它们正确地撤离. (稍后会呈现菜单...)

And the part I'm struggling with is registering the child routes, and have them evaulate correctly when navigating to them. (Rendering the menu would come later...)

// Load routes              router.map(routes.navRoutes).buildNavigationModel().mapUnknownRoutes(function(instruction)
{
    logger.logError('No Route Found', instruction.fragment, 'main', true);
});

// Try load child routes...
$.each(routes.navRoutes, function(index, parentRoute) {
     if (!parentRoute.childRoutes) {
                return;
            }

            var childRouter = router.createChildRouter()
                .makeRelative({
                    moduleId: parentRoute.moduleRootId,
                    fromParent: true // also tried false + non-splat routes...
                }).map(parentRoute.childRoutes).buildNavigationModel();
        });

在获取此导航结果时,我遇到了各种错误.尝试计算哈希(从未激活的父节点或子节点)时,通常是内部router.js错误-因此,所有哈希都已定义.

I've encountered various errors in getting this nav to render. Mostly internal router.js errors when trying to calculate the hash (either from a non-activated parent, or the child) - so all hashes have been defined.

一旦我得到了它来映射导航,子路线似乎就无法访问-他们只会加载主splat页面而不会出现错误.

Once I've got it to map the navigation, the child routes don't seem to be accessible - they just load the main splat page without error.

所以我想知道我是否正以正确的方式进行操作? (预先注册所有子路由,目的是要呈现一个2层菜单).

So I'm wondering if I'm going about this the right way at all? (Registering all child routes up front, with the goal of being about to render a 2-tier menu).

我认为回退使用的是类似 Durandal 1.2有关子路由的答案,平面路由注册,自定义"isSameItem"功能和计算的观测值以呈现2层导航.

I'm thinking the fallback is using something like the Durandal 1.2 answer about subrouting, using a combination of flat routing registration, custom 'isSameItem' function & computed observables to render the 2-tier navigation.

推荐答案

我希望我能对您有所帮助.

I do hope I can help You a bit.

您可以永久加载子"路由器吗?

据我所知,你做不到(或者没有简单的方法来实现这一目标).子路由器旨在为特定视图提供子路由功能-您可以将它们视为Durandal视图内的Durandal导航.如果我们在Durandal页面上检查示例代码,我们可以很容易地看到子路由的生存时间与给定的视图有关.而且,如果我们检查创建子路由的功能代码,将会看到它创建了新路由器,并且仅存储对父路由器的引用-父路由器(在大多数情况下,主路由器)没有对其子进程的引用

As far I know You can't ( or rather there is not simple way to achieve that). Child routers are designed to provide sub-routing capability for particular view - You can think about them as a Durandal navigation inside Durandal view. If we check the example code on Durandal page we can easily see that child routing life-time is connected with given view. What is more if we check the code of function creating child routes we will see that it creates new router and only store reference to parent router - the parent router ( in most cases main router) does not have references to its childs

router.createChildRouter = function() {
            var childRouter = createRouter();
            childRouter.parent = router;
            return childRouter;
        }; 

如何在主路由器中实现多级路由?

过去我也遇到过类似的问题,但是旧版本的Durandal.对于这个问题,我从头开始,您给了它一点点并对其进行了修改-我摆脱了splat路由,因为它打算与子路由一起使用,而我的解决方案将不使用它们.

I had similar problem in the past but with old version of Durandal. For this problem I had started from scratch You gave and modifed it a bit - I get rid of splat route as its intend to use with child routes and my solution will not use them.

var routes = [
                {
                    route: ['', 'home'],
                    moduleId: 'viewmodels/home',
                    title: 'Validation test',
                    nav: true
                },
                {
                    route: 'knockout-samples',
                    moduleId: 'viewmodels/ko/index',
                    moduleRootId: 'viewmodels/ko', // Custom property to make child routes easier              
                    title: 'Knockout Samples',
                    nav: true,
                    hash: '#knockout-samples',
                    childRoutes: [
                        { route: 'simpleList', moduleId: 'simpleList', title: 'SimpleList',  nav: true, hash : 'simpleList' },
                        { route: 'clickCounter', moduleId: 'clickCounter', title: 'Click Counter', nav: true, hash : 'clickCounter' }
                    ]
                }
            ];

下一步是将该用户友好的定义转换为路由表,该表可以轻松地在主路由器中注册.

Next step is converting this user-friendly definition to route table which can be easily register in main router.

$.each(routes, function(index, route) {
                if (route.childRoutes === undefined)
                    return
                $.each(route.childRoutes, function(index, childRoute) {
                    childRoute.route = route.route + '/' + childRoute.route;
                    childRoute.moduleId = route.moduleRootId + '/' + childRoute.moduleId;
                    childRoute.title = route.title + '/' + childRoute.title;
                    childRoute.hash = route.hash + '/' + childRoute.hash;
                    childRoute.parent = route.moduleRootId;
                });
                routes = routes.concat(route.childRoutes);
            });

最后一步是标准注册路由器并激活它.

Last step is standard registering router and activating it.

return router.map(routes)
                .buildNavigationModel()
                .activate();

如何呈现寄存器路由,以便保留多层布局?

我的代码可与Bootstrap 2.3.0一起使用,并将多级菜单呈现为下拉按钮.当route没有子路由(简单路由也是如此)并且没有父路由(其第一级导航)时,将被呈现为简单按钮.如果route有子路由,则将其呈现为下拉按钮,并将子路由添加到下拉列表中.

My code works with Bootstrap 2.3.0 and render multilevel menu as dropdown button. When route has no child routes ( so is just simple route) and has no parent ( its 1st level navigation) is rendered as simple button. If route has child routes its rendered as dropdown button and child routes are added to dropdown list.

<div class="btn-group" data-bind="foreach: router.navigationModel">
            <!-- ko if: $data.childRoutes === undefined && $data.parent === undefined -->
                <a data-bind="css: { active: isActive }, attr: { href: hash }, text: title" class="btn btn-info" href="#"/>
            <!-- /ko -->
            <!-- ko if: $data.childRoutes !== undefined -->
            <div class="btn-group btn-info">
                <a data-bind="css: { active: isActive }, attr: { href: hash }, text: title" class="btn btn-info" href="#"/>
                <button class="btn btn-info dropdown-toggle" data-toggle="dropdown">
                    <span class="caret"/>
                </button>
                <ul class="dropdown-menu" data-bind="foreach: childRoutes">
                    <a data-bind="css: { active: isActive }, attr: { href: hash }, text: title" class="btn btn-info" href="#"/>
                </ul>
            </div>
            <!-- /ko -->
        </div>

样式可能需要打磨,但整体逻辑已经完成.

The styles probably need to be bit polished but overall logic is done.

这篇关于Durandal 2.0-用于嵌套菜单的子路由器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆