2013-10-20 15 views
8

Ich habe eine App erstellt und möchte ein 2-stufiges Menü anzeigen, wobei beide Ebenen immer verfügbar sind. Durandal 2.0 introduced their new router, die "Kind-Router" unterstützt, die eine einfachere Deeplinking ermöglichen.Durandal 2.0 - Child Router für verschachtelte Menüs?

Meine Frage - Kann ich meine 'Kind'-Navigationsrouten dauerhaft laden lassen (und ein Untermenü gerendert, wenn der Elternteil nicht aktiv ist), oder ist das' Kindrouter'-Design dazu gedacht, sie zu bewerten Sind sie einmal ein Deeplink zu bewerten?

Durandal Die Beispiele zeigen Hauptnavigation ein Splat Route registrieren, dann wenn diese Ansicht Modell/aktiviert geladen wird, wird der Sohn-Router registriert.

Beispiel: In dem Beispiel mit Durandal bereitgestellt 2.0 wird der Mian nev 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(); 

registriert Und das ko/index.js View-Modell registriert dann die Kinder (auf 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(); 

Während Ich suche nach Definieren Sie meine Routen an einem Ort, zB:

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} 
     ]} 
    ]) 

Und der Teil, mit dem ich kämpfe, registriert die untergeordneten Routen und lässt sie korrekt auswerten, wenn sie zu ihnen navigiert. (Das Menü Rendern würde später kommen ...)

// 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(); 
     }); 

ich verschiedene Fehler in immer diese nav zu machen erlebt habe. Meistens interne router.js Fehler beim Versuch, den Hash zu berechnen (entweder von einem nicht aktivierten Eltern oder dem Kind) - so wurden alle Hashes definiert.

Sobald ich es habe, die Navigation zuzuordnen, scheinen die Child-Routen nicht zugänglich zu sein - sie laden nur die Haupt-Splat-Seite ohne Fehler.

Also ich frage mich, ob ich über den richtigen Weg überhaupt gehe? (Alle Kinderrouten im Voraus registrieren, mit dem Ziel, ein 2-stufiges Menü darzustellen).

Ich denke, das Notfall so etwas wie die Durandal 1.2 answer about subrouting verwendet, eine Kombination aus flacher Routing-Registrierung verwenden, custom ‚isSameItem‘ Funktion & Observablen berechnet, um die 2-Tier-Navigation zu machen.

Antwort

14

Ich hoffe ich kann dir ein wenig helfen.

Können Sie "Kinder" -Router dauerhaft geladen haben?

Soweit ich weiß kann man nicht (oder eher gibt es keinen einfachen Weg, das zu erreichen). Child-Router sind so konzipiert, dass sie Unterverteilungsfunktionen für bestimmte Ansichten bieten. Sie können diese als Durandal-Navigation in der Durandal-Ansicht betrachten. Wenn wir den Beispielcode auf der Durandal-Seite überprüfen, können wir leicht erkennen, dass die Lebenszeit des Child-Routings mit der gegebenen Ansicht verbunden ist.Wenn wir den Code der Funktion überprüfen, die untergeordnete Routen erstellt, sehen wir, dass er einen neuen Router erstellt und nur den Bezug zum übergeordneten Router speichert - der übergeordnete Router (in den meisten Fällen der Hauptrouter) hat keine Referenzen auf seine untergeordneten Objekte

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

Was kann getan werden, um mehrstufiges Routing im Hauptrouter zu erreichen?

Ich hatte ein ähnliches Problem in der Vergangenheit, aber mit der alten Version von Durandal. Für dieses Problem hatte ich von Grund auf neu begonnen. Sie haben es ein bisschen verändert und modifiziert - ich werde die Route von splat los, wie es mit Kind-Routen verwendet werden soll, und meine Lösung wird sie nicht benutzen.

Im nächsten Schritt wird diese benutzerfreundliche Definition in eine Routentabelle umgewandelt, die einfach im Hauptrouter registriert werden kann.

$.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); 
      }); 

Im letzten Schritt wird der Router standardmäßig registriert und aktiviert.

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

Wie Register zu machen, so Multi-Level-Layout Routing erhalten bleibt?

Mein Code arbeitet mit Bootstrap 2.3.0 und rendere Multilevel-Menü als Dropdown-Taste. Wenn die Route keine untergeordneten Routen hat (also nur eine einfache Route ist) und keine Eltern hat (ihre Navigation auf der ersten Ebene) wird als einfache Schaltfläche gerendert. Wenn die Route untergeordnete Routen hat, werden ihre als Dropdown-Schaltfläche gerenderten und untergeordneten Routen zur Dropdown-Liste hinzugefügt.

Die Stile müssen wahrscheinlich etwas poliert werden, aber die gesamte Logik ist getan.

+0

Ich habe in der Vergangenheit einen anderen Ansatz verwendet, um dies mit Eigenschaften auf den Router-Objekten zu tun, aber ich denke, das ist ein bisschen eleganter und ich mag diese Lösung wirklich. – MattSizzle

Verwandte Themen