2013-04-30 72 views
0

在这个简单的要求/骨干网应用Require.js模块没有看到骨干Router.js

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

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

这里是app.js

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

第一线,这里是TestView.js

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

检查出完整的详细信息,下载回购的第一线,运行和检查控制台日志如果你觉得如此倾向

谢谢! Jim

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

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

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

但是,这似乎是一个耻辱,路由器是不能直接访问无处不在,是上述方法中好的做法呢?

回答

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

+0

谢谢,是的,我从那以后意识到我有一个循环依赖 - 我想我正在考虑路由器在整个应用程序可用的单身人士,所以......这是考虑好的做法是绕过路由器,也可以使用require()内联来说话吗? – Jim 2013-05-01 09:52:25

+1

我试图解决你在路由器中查看路由的问题。但是现在,既然您已经问过这个问题的好坏,我想我不会选择这种方式,因为它会导致组件紧密结合。相反,我会让路由器监听视图的事件并调用视图的方法。所以如果视图需要路由器做某件事情,它会触发事件。如果路由器需要使用视图,它将调用它的公共方法。 – 2013-05-01 12:13:30

0

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

  1. require.js只适用于AMDs。由于主干不再支持AMD。您将需要使用启用BackboneAMD版本。你可以得到它here

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

您可能想要改进编码模式。这里是我的建议:

App.js

define([ 

'骨干', '路由器', ]功能(骨干,MainRouter){ '使用严格的';

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:你为什么要在视图中使用的路由器?我已经构建了很多骨干应用程序。从来没有需要这样做。

+0

嗨,1)没有意识到主干不再是AMD谢谢2)是的,自从发布我意识到有一个循环依赖3)我想我想'路由器'就像整个应用程序可用的单身人士,原因我想在视图中使用它是因为对话框上的关闭按钮应该启动另一个视图4)但是..我已经意识到我有点误解了路由器的使用 - 我正在使用一个事件调度员现在改为 – Jim 2013-05-01 09:50:16

+0

伟大,你正在做你的研究。我已经添加了您可能想要遵循的示例模式。我一直在使用它。好像你可能想要使用事件。您可以触发事件并在另一个视图中侦听它。我将为此添加一些示例代码。 – Subash 2013-05-01 09:55:06

+0

谢谢!我是一个闪光/动作难民:)迄今我loooooooving JavaScript - 上次我碰它是十年前,OMG!它长大了 - 对不起话题 – Jim 2013-05-01 11:04:31

0

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

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