Dan*_*tar 32 backbone.js backbone-routing
我在几个地方读过,调用Backbone.history.navigate函数被认为是不好的做法.
例如Addy Osmani sais在他的书"开发Backbone.js应用程序"中
Router.navigate()也可以通过传递trigger:true选项来触发路由以及更新URL片段.注意:不鼓励这种用法......
http://addyosmani.github.io/backbone-fundamentals/#backbone.history
或者Derick Bailey在他的博客文章中甚至是sais:
在大多数情况下,您不应该在应用程序中执行路由的处理程序.
但我真的不明白它背后的原因以及什么是更好的解决方案.
在我看来,使用trigger:true选项调用导航功能并不是很糟糕.路由功能可以在调用时始终检查所考虑的数据是否已加载并显示此加载的数据,而不是重新执行整个工作...
Cre*_*ers 25
Router#navigate我认为,对于究竟是什么,似乎存在一些混淆.
如果没有设置任何选项,它将更新提供的片段的URL.例如,router.navigate('todo/4/edit')将URL更新为#todo/4AND将为该URL 创建浏览器历史记录条目.没有路由处理程序运行.
但是,设置trigger:true将更新URL,但它也将运行为该路由指定的处理程序(在Addy的示例中,它将调用路由器editTodo函数)并创建浏览器历史记录条目.
传递replace:trueurl时会更新,不会调用任何处理程序,但不会创建浏览器历史记录条目.
然后,我认为答案是:
trigger:true不鼓励使用的原因很简单,从应用程序状态导航到应用程序状态到应用程序状态需要大部分时间运行不同的代码,而不是直接导航到特定的应用程序状态.
假设您的应用程序中有A,B和C状态.但是状态B构建在状态A上,状态C构建在B上.在这种情况下,当你从B导航到C时,只需要执行特定的代码部分,而当直接命中状态C时,可能会执行一些状态检查和准备:
等等
我们举一个例子:State A(#list)显示歌曲列表.状态B(#login)与用户认证有关,状态C(#list/edit)允许编辑歌曲列表.
因此,当用户登陆状态A时,歌曲列表被加载并存储在集合中.他点击登录按钮并重定向到登录表单.他成功验证并重定向回歌曲列表,但这次使用歌曲旁边的删除按钮.
他书签了最后一个州(#list/edit).
现在,当用户几天后点击书签时需要做什么?应用程序需要加载歌曲,需要验证用户是否(仍然)登录并做出相应的反应,状态转换流程中的内容已经在其他状态中完成.
现在请注意我自己:
我不会像在示例中那样在实际应用程序中推荐上述方法.您应该检查从B到C时是否加载了集合,而不仅仅假设它已经存在.同样,您应该检查用户是否确实已登录.这只是一个示例.
IMO路由器确实是一种特殊的视图(考虑它,它显示应用程序状态并将用户输入转换为应用程序状态/事件),并且应始终如此对待.你永远不应该依赖路由器在状态之间转换,而是让路由器反映状态转换.
mor*_*mor 11
我不得不在这里不同意@ Stephen的回答.而主要原因是因为使用router.navigate({trigger : true})路由器负责处理应用程序的状态.它应该只反映应用程序状态,而不是控制它.
此外,View更改窗口的哈希不是一个责任,这是路由器唯一的工作!不要把它拿走!良好的模块化和关注点分离使得可扩展和可维护的应用程序成为可能.
Backbone是一个事件驱动的框架,使用事件进行通信.完全没有必要调用,router.navigate({ trigger : true })因为功能不应该在路由器中.以下是我如何使用路由器的示例,我认为可以促进良好的模块化和关注点分离.
var Router = Backbone.Router.extend({
initialize: function(app) {
this.app = app;
},
routes: {
'videoLibrary' : function() { this.app.videoLibrary(); }
}
});
var Application = _.extend({}, Backbone.Events, {
initialize: function() {
this.router = new Router( this );
this.listenTo( Backbone, 'video:uploaded', function() {
this.router.navigate('/videoLibrary');
this.videoLibrary();
});
},
videoLibrary: function() {
//do useful stuff
}
});
var uploadView = Backbone.View.extend({
//...
uploadVideo: function() {
$.ajax({
//...
success: function() { Backbone.trigger('video:uploaded'); }
});
}
});
Run Code Online (Sandbox Code Playgroud)
您的观点并不需要或想要知道,当用户上传完成的事,这是别人的责任.在此示例中,路由器只是应用程序功能的入口点,由uploadView另一个生成的事件.路由器始终通过哈希更改和历史记录反映应用程序状态,但不实现任何功能.
通过分离问题,您可以增强应用程序的可测试性.间谍很容易,Backbone.trigger并确保视图正常工作.模拟路由器不太容易.
此外,如果您使用某些模块管理(如AMD或CommonJS),则必须在应用程序中的任何位置传递路由器的实例才能调用它.因此,在您的应用程序中具有紧密耦合,这不是您想要的.