Using the Backbone.js router to navigate through v

2019-01-30 01:35发布

I am separating my views and router into separate files with require. I then have a main.js file that instantiates the router, and also renders my default view.

My router has view ('View/:id') and edit ('Edit/:id') as routes. In main.js, when I instantiate the router, I can hardcode router.navigate('View/1', true) and the navigation works fine. In my view file, when I click on the edit link, I want to call router.navigate('View/' + id, true), but I'm not sure how I should do this.

I've had success calling Backbone.history.navigate('View/' + id, true), but I don't feel like I should be relying on the global Backbone object.

I tried passing ({ router: appRouter }) to my views so I could use this.options.router.navigate(), however that wasn't working for me.

In case you're curious, here's a bunch of code from my app:

Router:

define(['./View', './Edit'], function (View, Edit) {
    return Backbone.Router.extend({
        routes: {
            'View/:id': 'view',
            'Edit/:id': 'edit'
        },

        view: function (id) {
            var model = this.collection.get(id);
            var view = new View({ model: model });
            view.render();
        },

        edit: function (id) {
            var model = this.collection.get(id);
            var edit = new Edit({ model: model });
            edit.render();
        }
    });
});

View:

define(function () {
    return Backbone.View.extend({
        template: Handlebars.compile($('#template').html()),

        events: {
            'click .edit': 'edit'
        },

        render: function () {
            //Create and insert the cover letter view
            $(this.el).html(this.template(this.model.toJSON()));
            $('#View').html(this.el);

            return this;
        },

        edit: function () {
            Backbone.history.navigate('Edit/' + this.model.id, true); 
        },
    });
});

8条回答
姐就是有狂的资本
2楼-- · 2019-01-30 02:23

I have a new solution for routing AMD modules.

RequireJS Router https://github.com/erikringsmuth/requirejs-router

This takes the approach of lazy loading AMD modules as you navigate to each page. With the Backbone router you need to require all of your views as dependencies up front. This loads all of your apps Javascript on the first page load. The RequireJS Router lazy loads modules as you navigate to each route.

Example main.js used to run your app

define([], function() {
  'use strict';

  // Configure require.js paths and shims
  require.config({
    paths: {
      'text': 'bower_components/requirejs-text/text',
      'router': 'bower_components/requirejs-router/router'
    }
  });

  // Load the router and your layout
  require(['router', 'js/layout/layoutView'], function(router, LayoutView) {
    var layoutView = new LayoutView();
    // The layout's render method should draw the header, footer, and an empty main-content section
    // then load the content section.
    // render: function() {
    //   this.$el.html(this.template({model: this.model}));
    //   router.loadCurrentRoute();
    // }

    // Configure the router
    router
      .registerRoutes({
        home: {path: '/', moduleId: 'home/homeView'},
        order: {path: '/order', moduleId: 'order/orderView'},
        notFound: {path: '*', moduleId: 'notFound/notFoundView'}
      })
      .on('statechange', function() {
        // Render the layout before loading the current route's module
        layoutView.render.call(layoutView);
      })
      .on('routeload', function(module, routeArguments) {
        // Attach the content view to the layoutView's main-content section
        layoutView.$('#main-content').replaceWith(new module(routeArguments).render().el);
      })
      .init({
        // We're manually calling loadCurrentRoute() from layoutView.render()
        loadCurrentRouteOnStateChange: false
      });
  );
);
查看更多
干净又极端
3楼-- · 2019-01-30 02:26

What about this approach? As backbone implements the template pattern in all its 4 components, with a little of design you can provide to each view an easy navigation mechanism through the app's router without needing to make any circular reference (this was something I saw in other similar posts, but try to avoid it).

Router component, not to much different from other router examples:

define('Router', ['backbone', ... ],
        function (Backbone, ...) {

            var MyRouter = Backbone.Router.extend({
                routes: {
                    'viewA': 'viewA',
                    'viewB': 'viewB'
                },

                initialize: function () {
                    ...
                };
            },
            viewA: function () {
                ...
            },

            viewB: function () {
                ...
            }
});

return MyRouter;
});

App, creates the router instance and fires the first view passing this instance:

define('App', ['backbone', ...
], function (Backbone, ...) {

    function initialize() {

        //route creation
        if (!this.routes)
            routes = new Router(this); 
        //backbone history start
        Backbone.history.start();

        //ViewA navigation, bigbang
        if (!this.viewA)
            this.viewA = new ViewA({router: this.routes});
        this.viewA.render();
    }

    return {
        initialize: initialize
    };
});

BaseView, base constructor definition for all views and also a navigation method:

define('BaseView', ['jquery', 'underscore',  'backbone', ...
], function ($, _, Backbone, ...) {
    var BaseView;

    BaseView = Backbone.View.extend({
        id: '...',

        constructor: function (options) {
            this.router = options.router;
            this.model = options.model;
            Backbone.View.prototype.constructor.call(this);
        },
        initialize: function () {
            this.template = _.template(tpl);
        },

        events: {

        },
        render: function () {
            $(this.el).html(this.template());

            return this;
        },
        //Provides transparent navigation between views throught the backbonejs
        //route mechanism
        navigate: function(pageId)
        {
            this.router.navigate(pageId, {trigger: true});
        }
    });

    return BaseView;
});

A View instance, each view extends from the base one instead of backbone, and inherits base behavior:

define('ViewA', ['jquery', 'underscore',  'backbone', 'BaseView'
], function ($, _, Backbone, BaseView) {
    var ViewA;

    ViewA = BaseView.extend({
        id: '...',

        constructor: function (options) {
            this._super("constructor");
        },

        ...
        foo: function()
        {
            ...

            this.navigate("viewB");
        }
    });

    return ViewA;
});

It works for me, and also it can be reuse in other projects.

查看更多
登录 后发表回答