Routing in Backbone.js / Marionette.js - no hashta

2019-03-17 03:31发布

问题:

I have three questions about routing in Backbone.js / Marionette.js :

  • 1) How can I get a list of all the routes my application's routers have registered ?

For example for Express.js (in Node.js) it would be app.routes.

I'm trying to do the same with Backbone.js / Marionette.js but couldn't find any property or method that did this.

  • 2) I want to clean-up my URLs and remove the hashtag "#" in front of them, I know that they trigger the Routers so how can I manage to do this ?

I found the following script that prototypes the Backbone router, but it's more of a hack than a stable solution : Simple backbone routing without hash URLs

  • 3) Is is possible to have sub-routers in Backbone.js / Marionette.js ?

What I mean by sub-router is a router which only handles a part of a url, e.g :

var AppRouter = Backbone.Router.extend({
    routes: {
        'articles' : 'MyArticleRouter'
    }
});

var MyArticleRouter = Backbone.Router.extend({
    routes: {
        'science' : 'someMethod',
        'literrature' : 'someOtherMethod'
    }
});

This would categorise my URLs a little bit more by letting me define the main routes in AppRouter and all the subroutes (part after the second slash "/") in category-specific sub-routers.

So for the following URL : "hostname/articles/science", the routing process would look something like this :

  • 1) pass "/articles/science" to AppRouter
  • 2) AppRouter splits the URI and takes the "/articles" part
  • 3) AppRouter finds the registered "/articles" route
  • 4) AppRouter recognises that MyArticleRouter is bound to that URI element
  • 5) AppRouter forwards the routing to that router and only passes the "/science" element as a route
  • 6) MyArticleRouter routes "/science" to the someMethod() and runs it

Thank you in advance !

回答1:

Answer for #1:

All the routes are registered in Backbone.history.handlers.

Answer for #2:

You can add a handler to every link in your site:

var application = new Backbone.Marionette.Application();

application.addInitializer(function(options) {
    // Add class to target a browser, not as standalone app.
    if(window.navigator.standalone != true) {
        $('body').addClass('no-standalone');
    }

    // Prevent internal links from causing a page refresh.
    $(document).on('click', 'a', function(event) {
        var fragment = Backbone.history.getFragment($(this).attr('href'));
        var matched = _.any(Backbone.history.handlers, function(handler) {
            return handler.route.test(fragment);
        });
        if (matched) {
            event.preventDefault();
            Backbone.history.navigate(fragment, { trigger: true });
        }
    });
});

Of course make sure you use pushState:

    if (!Backbone.history.started) {
        Backbone.history.start({ pushState: true });
    }

That last snippet must be run after you have initialized all your routers.

Answer for #3:

This may work a little to split your routes:

define([
    'backbone',
    'underscore',
    'routers/dashboard',
    'routers/anotherroute1',
    'routers/anotherroute2'
],

function(Backbone, _, DashboardRouter, AnotherRoute1, AnotherRoute2) {
    'use strict';

    var application = new Backbone.Marionette.Application();

    application.addInitializer(function () {

        _.each([DashboardRouter, AnotherRoute1, AnotherRoute2], function(router) {
            new router();
        });

        if (!Backbone.history.started) {
            Backbone.history.start({ pushState: true });
        }
    });

    return application;
});