可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
In this simple Require/Backbone app
https://github.com/thisishardcoded/require-prob
Why does app.js see Router but TestView.js not?
Here is the first line of app.js
define(['router'],function (Router) {
and here is the first line of TestView.js
define(['backbone','router'],function(Backbone,Router){
Check out the repo for full details, download, run and check console log if you feel so inclined
Thanks!
Jim
More: Ok, the answer is - because of the order in which it is loaded and even if that were altered I have a circular dependency don't I? TestView needs Router, Router needs TestView.
In which case the solution might be
var r=require('router);
r.navigate or whatever
but, that seems like a shame that Router is not directly accessible everywhere and, is the above method good practice anyway?
回答1:
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
回答2:
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
回答3:
I downloaded and inspected your code. Following could be the issues:
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
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.
回答4:
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;
},