为了简化路由,Marionette 引入了 AppRouter 的概念。用上它之后,就不用再写那些路由事件处理的繁琐代码了,并且可以将路由器配置为直接调用某个对象上的方法。我们用appRoutes配置AppRouter。
原来用Backbone时,我们要在路由器Workspace中定义 '*filter': 'setFilter' 路由:
var Workspace = Backbone.Router.extend({ routes:{ '*filter': 'setFilter' }, setFilter: function( param ) { // Set the current filter to be used window.app.TodoFilter = param.trim() || ''; // Trigger a collection reset/addAll window.app.Todos.trigger('reset'); } });
尽管我们用上了可读性很强的Layouts,但原来在AppView and TodoView中的显示逻辑并没有挪过去,也要由TodoList 控制器处理。
TodoMVC.TodoList.js:
TodoMVC.module('TodoList', function(TodoList, App, Backbone, Marionette, $, _){ // TodoList Router // --------------- // // Handle routes to show the active vs complete todo items TodoList.Router = Marionette.AppRouter.extend({ appRoutes : { '*filter': 'filterItems' } }); // TodoList Controller (Mediator) // ------------------------------ // // Control the workflow and logic that exists at the application // level, above the implementation detail of views and models TodoList.Controller = function(){ this.todoList = new App.Todos.TodoList(); }; _.extend(TodoList.Controller.prototype, { // Start the app by showing the appropriate views // and fetching the list of todo items, if there are any start: function(){ this.showHeader(this.todoList); this.showFooter(this.todoList); this.showTodoList(this.todoList); this.todoList.fetch(); }, showHeader: function(todoList){ var header = new App.Layout.Header({ collection: todoList }); App.header.show(header); }, showFooter: function(todoList){ var footer = new App.Layout.Footer({ collection: todoList }); App.footer.show(footer); }, showTodoList: function(todoList){ App.main.show(new TodoList.Views.ListView({ collection : todoList })); }, // Set the filter to show complete or all items filterItems: function(filter){ App.vent.trigger('todoList:filter', filter.trim() || ''); } }); // TodoList Initializer // -------------------- // // Get the TodoList up and running by initializing the mediator // when the the application is started, pulling in all of the // existing Todo items and displaying them. TodoList.addInitializer(function(){ var controller = new TodoList.Controller(); new TodoList.Router({ controller: controller }); controller.start(); }); });
在这个应用中,Controller并没有给总体工作流添加太多东西。通常来说,按Marionette的观点,应用中的routers应该是深思熟虑后的成果。可是,开发人员经常滥用Backbone的路由系统,整个程序的工作流和逻辑都放到一个控制器里。
结果每种可能的代码组合都不可避免地放到了router方法中,创建view,加载model,协调应用中的不同部分等等。Drick觉得这破坏了单一职责原则 (SRP) 和 关注点分离原则。
Backbone的router和history是为了解决浏览器特定问题的 - 管理 forward 和 back 按钮。Marionette 认为应该把他们的权力关在笼子里,不让他们碰通过导航执行的代码。这样应用有没有router都能用。我们可以从按钮点击事件上,从应用的事件处理器上,或者从router上调用controller的show方法,并且不管如何调用哪个方法,我们最终得到的应用状态都是一样的。
Derick 把他对这一主题的想法都写在了他的blog上,你如果感兴趣可以去看看:
- http://lostechies.com/derickbailey/2011/12/27/the-responsibilities-of-the-various-pieces-of-backbone-js/
- http://lostechies.com/derickbailey/2012/01/02/reducing-backbone-routers-to-nothing-more-than-configuration/
- http://lostechies.com/derickbailey/2012/02/06/3-stages-of-a-backbone-applications-startup/
转载请注明:阿尤博客 » Marionette:Marionette App:Todo_路由器 AppRouter 及 Controller(三)