Require.js模块没有看到Backbone Router.js

时间:2013-04-30 20:43:26

标签: backbone.js requirejs amd

在这个简单的需求/骨干应用

https://github.com/thisishardcoded/require-prob

为什么app.js看到路由器而不是TestView.js?

这是app.js的第一行

define(['router'],function (Router) {

这是TestView.js的第一行

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

如果你有这种倾向,请查看回购以获取完整的详细信息,下载,运行并检查控制台日志

谢谢! 吉姆

更多:好的,答案是 - 因为它的加载顺序,即使它被改变了,我有一个循环依赖不是吗? TestView需要路由器,路由器需要TestView。

在哪种情况下,解决方案可能是

var r=require('router);
r.navigate or whatever

但是,路由器到处都无法直接访问似乎很遗憾,无论如何,上述方法是不是很好的做法?

4 个答案:

答案 0 :(得分:5)

肯定是因为循环依赖而发生的。要解决此问题,您可以将路由器传递给视图的构造函数并从视图的模块中删除路由器依赖项,或者在视图中使用require('router')。

第一个选项,router.js:

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

第一个选项,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;

});

第二个选项,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;

});

此处还介绍了第二个选项:http://requirejs.org/docs/api.html#circular

答案 1 :(得分:0)

您应该在baseUrl文件中定义包含RequireJS配置的main.js属性。 这样,应用程序中模块的所有路径都将相对于baseUrl

请参阅:

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

答案 2 :(得分:0)

我下载并检查了您的代码。以下可能是问题:

  1. require.js仅适用于AMDs。由于骨干网不再支持AMD。您需要使用AMD启用的Backbone版本。你可以得到它here

  2. TestView是您在路由器中的依赖项。所以它在加载路由器之前加载。

  3. 您可能希望改进编码模式。这是我的建议:

    App.js

    define([
    

    '骨干',   '路由器', ],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;
    });
    

    修改 听取事件:

    // 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:你为什么要在视图中使用路由器?我已经构建了很多主干应用程序。永远不需要这样做。

答案 3 :(得分:0)

您可以使用可用的Backbone.history.navigate来更轻松地实现目标,因为Router.navigate是一个简单的包装器。考虑这个part of Backbone source

navigate: function(fragment, options) {
  Backbone.history.navigate(fragment, options);
  return this;
},