Require.js module not seeing Backbone Router.js

僤鯓⒐⒋嵵緔 提交于 2019-12-04 21:12:02

Surely it happens because of circular dependency. To resolve it, you either pass router to view's constructor and remove router dependency from view's module, or use require('router') in your view.

1st option, router.js:

app_router.on('route:test', function () {
    var testView = new TestView({router: app_router});
    testView.render();
})

1st option, view.js:

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

    var TestView=Backbone.View.extend({
        el: '#test',
        initialize: function() {
            // get router from constructior options
            this.router = this.options.router
        },
        render: function(){
            this.$el.html('<p>Foo!</p>');
            console.log("TestView.js does not find 'Router',", this.router);
        }
    });

    return TestView;

});

2nd option, view.js:

define(['backbone','router'], function(Backbone, router){

    // at this point router module is not loaded yet so router is undefined

    var TestView=Backbone.View.extend({
        el: '#test',
        initialize: function() {
            // at this point router module is loaded and you may access it with require call
            this.router = require('router');
        },
        render: function(){
            this.$el.html('<p>Foo!</p>');
            console.log("TestView.js does not find 'Router',", this.router);
        }
    });

    return TestView;

});

2nd option is also described here: http://requirejs.org/docs/api.html#circular

You should define baseUrl property in your main.js file that contains RequireJS config. In this way all paths to modules in your application will be relative to that baseUrl.

See:

http://requirejs.org/docs/api.html#jsfiles
http://requirejs.org/docs/api.html#config-baseUrl

I downloaded and inspected your code. Following could be the issues:

  1. require.js only works with AMDs. Since backbone no longer supports AMD. You will need to use AMD enabled version of Backbone. You can get it here

  2. TestView is the dependency in you Router. So it loads before the Router is loaded.

You might want to improve the coding pattern. Here is my suggestion:

App.js

define([

'backbone', 'router', ], function(Backbone, MainRouter){ 'use strict';

var AppView = Backbone.View.extend({

    initialize: function(){

        App.router = new MainRouter();
        Backbone.history.start();
    }
});

return AppView;
});

Router.js

define([
  'backbone',
  'view/TestView'
], function(Backbone, TestView){
    var Main = Backbone.Router.extend({
        routes: {
            'test': 'test'
        },

        test: function(){
            new TestView({
                // pass model or collection to the view
                // model: new TestModel // remember to require
            });
        }

    });

    return Main;
});

EDIT Listening to events:

// in main.js
var window.Vent = {};

_.extend(window.Vent, Backbone.Events);

// now in any view you can trigger a event
$('something').on('click', function(){
    window.Vent.trigger('somethinghappened', this); 
    // this is reference to current object
});

// now in other view you can do
window.Vent.on('somethinghappened', this.run, this); 
// this in the end is the reference we passed when event was triggered

run: function(obj){
    //this function will run when the event is triggered
    // obj is the object who triggered the event
}

PS: why do you want to use router in view?? I have built quite a few backbone apps. Never needed to do so.

You can use available Backbone.history.navigate to achieve your goal easier, because Router.navigate is a simple wrapper for it. Consider this part of Backbone source:

navigate: function(fragment, options) {
  Backbone.history.navigate(fragment, options);
  return this;
},
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!