Emberjs——API/类/Ember.Router
Ember.Router Class
Emberjs API:http://emberjs.com/api/
继承自:Ember.StateManager
定义于:packages/ember-routing/lib/router.js:21
所属模块:ember-routing
说明:Ember.Router是Ember.StateManager的子类,负责提供基于URL的应用程序状态检测。在应用加载时,Ember.Router实例(指代应用中创建的路由器)检测浏览器的URL,并尝试与应用的某一个状态匹配。另外,路由器会实时更新URL来反映应用状态的更改。
添加路由器实例到应用程序
有两种方式可以实现应用程序与路由器的关联:
定义应用程序的Router属性,属性值时Ember.Router的子类。然后调用应用程序的initialize方法,路由器子类将自动实例化并开启路由检测。路由器实例将作为应用程序的router属性来使用:
App = Ember.Application.create({ Router: Ember.Router.extend({ ... }) }); App.initialize(); App.get('router') // an instance of App.Router
如果想在其它地方定义路由器实例,可以传递路由器实例给应用程序的initialize方法:
App = Ember.Application.create(); aRouter = Ember.Router.create({ ... }); App.initialize(aRouter); App.get('router') // aRouter
添加路由到路由器
路由器实例的initialState属性的值是root。该属性存储了路由状态,该状态必须是Ember.Route的子类。root路由本身是不可路由的,它是其它可路由状态的容器。它必须含有其它路由,这些路由包含一个route属性,用来描述URL格式。
App = Ember.Application.create({ Router: Ember.Router.extend({ root: Ember.Route.extend({ index: Ember.Route.extend({ route: '/' }), ... additional Ember.Routes ... }) }) }); App.initialize();
当应用程序加载,Ember会解析URL并在应用程序状态中尝试查找匹配的路由。
在以下路由结构中:
App = Ember.Application.create({ Router: Ember.Router.extend({ root: Ember.Route.extend({ aRoute: Ember.Route.extend({ route: '/' }), bRoute: Ember.Route.extend({ route: '/alphabeta' }) }) }) }); App.initialize();
用URL“#/”载入页面,将检测到“root.aRoute”(对应“/”)的route属性,然后控制路由器,首先进入“root”状态,然后进入其子状态“aRoute”。
同理,用URL“#/alphabeta”载入时,会检测到“root.bRoute”(对应“/alphabeta”)的route属性,然后先进入“root”状态,再进入子状态“bRoute”。
添加嵌套路由到路由器
路由可以包含嵌套的子路由,它们的route属性用于描述URL的嵌套部分,并用于检测和处理。正如StateManager实例,路由器不能调用transitionTo方法进入中间状态。为避免这种情况,嵌套的路由必须定义一个基础路由属性以及一个route属性值为“/”的子路由,当在URL检测到基础路由时,最终会进入定义的子路由。给定下面的应用程序代码:
App = Ember.Application.create({ Router: Ember.Router.extend({ root: Ember.Route.extend({ aRoute: Ember.Route.extend({ route: '/theBaseRouteForThisSet', indexSubRoute: Ember.Route.extend({ route: '/' }), subRouteOne: Ember.Route.extend({ route: '/subroute1' }), subRouteTwo: Ember.Route.extend({ route: '/subRoute2' }) }) }) }) }); App.initialize();
当载入URL“/theBaseRouteForThisSet”时,路由器会过渡到基础路由路径“root.aRoute”,然后过渡到状态“indexSubRoute”。
当载入URL“/theBaseRouteForThisSet/subRoute1”时,则先过渡到路由路径“root.aRoute”,再进入状态“subRouteOne”。
[只要有子路由存在,总会继续往下进入子状态,并且查找route属性为“/”的状态]
路由过渡事件
在路由实例间过渡时会触发与Ember.State状态过渡时同样的过渡事件。而默认的setup过渡事件则命名为connectOutlets(查阅下文“更改视图层次响应状态变化”)。
当以URL“#/”载入时,以下的路由结构
App = Ember.Application.create({ Router: Ember.Router.extend({ root: Ember.Route.extend({ aRoute: Ember.Route.extend({ route: '/', enter: function(router) { console.log("entering root.aRoute from", router.get('currentState.name')); }, connectOutlets: function(router) { console.log("entered root.aRoute, fully transitioned to", router.get('currentState.path')); } }) }) }) }); App.initialize();
将在控制台输出:
'entering root.aRoute from root' 'entered root.aRoute, fully transitioned to root.aRoute '
Ember.Route有两个回调函数用于处理URL的序列化与反序列化。(查阅“序列化/反序列化URLs”)
通过动态分段进行路由
路由的route属性可以通过URL中的“:”符号引用URL的动态分段。这些动态分段的值会以哈希对的形式传递给对应路由的deserialize方法(查阅“序列化/反序列化URLs”)。
序列化/反序列化URLs
Ember.Route有两个回调函数,用于关联具体对象上下文和URL:转换一个对象为哈希参数以填充URL动态分段的serialize方法,和转换一个URL动态段哈希到相关对象的deserialize方法。
反序列化一个URL动态分段
当应用开始加载或手动修改了URL(比如点击浏览器的后退按钮),与URL匹配的路由deserialize方法将被调用,并且应用程序的路由器(router)是第一个参数,URL动态分段的哈希值是第二个参数。
当加载URL“#/fixed/thefirstvalue/anotherFixed/thesecondvalue”,下面的路由结构:
App = Ember.Application.create({ Router: Ember.Router.extend({ root: Ember.Route.extend({ aRoute: Ember.Route.extend({ route: '/fixed/:dynamicSectionA/anotherFixed/:dynamicSectionB', deserialize: function(router, params) {} }) }) }) }); App.initialize();
将在路径“root.aRoute”调用路由实例的deserialize方法,第二个参数是下面的哈希对:
{ dynamicSectionA: 'thefirstvalue', dynamicSectionB: 'thesecondvalue' }
在deserialize里你应当使用这个信息去检索或为给定的URL创建一个合适的上下文对象。该对象必须是deserialize方法的返回值,并且被传递给路由的connectOutlets和serialize方法。
当应用程序自身更改了状态,过渡状态上下文将被传递,但deserialize方法不会被调用(查阅“在状态间过渡”)。
将对象序列化为URL动态分段
过渡到一个route属性含有动态分段的路由时,该路由的serialize方法被调用,路由所在的路由器router作为第一参数,该路由所处上下文作为第二参数。serialize返回的值用来填充动态分段,该值必须是一个带有与动态分段相匹配的键的对象。
给定以下路由结构:
App = Ember.Application.create({ Router: Ember.Router.extend({ root: Ember.Route.extend({ aRoute: Ember.Route.extend({ route: '/' }), bRoute: Ember.Route.extend({ route: '/staticSection/:someDynamicSegment', serialize: function(router, context) { return { someDynamicSegment: context.get('name') } } }) }) }) }); App.initialize();
假设上下文对象为Object.create({name: 'Yehuda'}),过渡到“root.bRoute”,将调用bRoute的serialize方法,上下文对象作为第二参数传递,最终更新URL的动态分段为“#/staticSection/Yehuda”。
在状态间过渡
一旦一个基于进入URL的可路由应用程序完成状态的初始化,随后的状态过渡,只要进入的路由有一个route属性,将更新URL。给定下面路由结构,以URL“#/”载入:
App = Ember.Application.create({ Router: Ember.Router.extend({ root: Ember.Route.extend({ aRoute: Ember.Route.extend({ route: '/', moveElsewhere: Ember.Route.transitionTo('bRoute') }), bRoute: Ember.Route.extend({ route: '/someOtherLocation' }) }) }) }); App.initialize();
应用程序代码:
App.get('router').send('moveElsewhere');
将转换到“root.bRoute”状态并触发URL更新为“#/someOtherLocation”。
send方法可以传递一个上下文对象作为第二参数。路由器会匹配动态分段到该对象的键上并用提供的值填充到URL。给定下面状态结构,载入URL“#/”:
App = Ember.Application.create({ Router: Ember.Router.extend({ root: Ember.Route.extend({ aRoute: Ember.Route.extend({ route: '/', moveElsewhere: Ember.Route.transitionTo('bRoute') }), bRoute: Ember.Route.extend({ route: '/a/route/:dynamicSection/:anotherDynamicSection', connectOutlets: function(router, context) {}, }) }) }) }); App.initialize();
应用程序代码:
App.get('router').send('moveElsewhere', { dynamicSection: '42', anotherDynamicSection: 'Life' });
将转换到状态“root.bRoute”并触发URL更新为“#/a/route/42/Life”。
这个上下文对象也会作为第二参数传递给serialize方法。
注入单一控制器
在应用程序初始化过程中,Ember会检测以“Controller”结尾的属性,并为这些类各自创建单个实例,然后将它们作为属性分配给路由器。属性名将由大写驼峰命名转换为小写驼峰命名格式。这些controller类必须是以下类的拓展子类:Ember.ObjectController, Ember.ArrayController, Ember.Controller,或者是自定义的包含混合类Ember.ControllerMixin的Ember.Object类。
App = Ember.Application.create({ FooController: Ember.Object.create(Ember.ControllerMixin), Router: Ember.Router.extend({ ... }) }); App.get('router.fooController'); // instance of App.FooController
这些单一控制器拥有namespace属性,指向应用程序,以及target属性,指向应用程序的路由器,方便与Ember的用户事件系统整合。查阅“更改视图层次响应状态变化”和“响应用户事件”。
响应用户事件
在应用程序初始化时,Controller实例注入到路由器,其target属性指向路由器实例。这些控制器实例同时作为相关联的视图的默认context对象。使用{{action}}助手将自动设置target为应用程序的路由器。
给定下面应用程序,以URL“#/”载入:
App = Ember.Application.create({ Router: Ember.Router.extend({ root: Ember.Route.extend({ aRoute: Ember.Route.extend({ route: '/', anActionOnTheRouter: function(router, context) { router.transitionTo('anotherState', context); } }) anotherState: Ember.Route.extend({ route: '/differentUrl', connectOutlets: function(router, context) { } }) }) }) }); App.initialize();
模板:
<script type="text/x-handlebars" data-template-name="aView"> <h1><a {{action anActionOnTheRouter}}>{{title}}</a></h1> </script>
将在渲染的h1元素上委托指向路由器实例的click事件。在这种情况下,root.aRoute状态的anActionOnTheRouter方法被调用,视图对应的控制器作为context参数。这个context会作为第二个参数传递给connectOutlets方法。
在{{action}}助手里可以提供不一样的context对象,允许传递状态间特定的上下文对象:
<script type="text/x-handlebars" data-template-name="photos"> {{#each photo in controller}} <h1><a {{action showPhoto photo}}>{{title}}</a></h1> {{/each}} </script>
查阅API Handlebars.helpers.action获取其他有用的示例。
更改视图层次响应状态变化
改变URL的状态更改伴随着相关的视图层次结构的变化。这可以在触发路由connectOutlets事件时,通过在注入的控制器实例上调用路由的connectOutlet方法来实现:
App = Ember.Application.create({ OneController: Ember.ObjectController.extend(), OneView: Ember.View.extend(), AnotherController: Ember.ObjectController.extend(), AnotherView: Ember.View.extend(), Router: Ember.Router.extend({ root: Ember.Route.extend({ aRoute: Ember.Route.extend({ route: '/', connectOutlets: function(router, context) { router.get('oneController').connectOutlet('another'); }, }) }) }) }); App.initialize();
这将查找oneController对应的视图view(App.OneView的实例)指定的模板中的{{outlet}}助手,渲染App.AnotherView的一个实例并填充到这个{{outlet}}中。App.AnotherView实例的context来自路由器的anotherController属性,该属性是App.AnotherController的一个实例。
查阅Ember.Handlebars.helpers.outlet获取更多关于Outlets的信息。查阅Ember.Controller.connectOutlet获取更多关于connectOutlet方法的信息。查阅Ember.Application#initialize()获取更多关于控制器注入的信息。查阅Ember.View获取更多关于视图上下文的信息。
继承的方法
-参阅Ember.StateManager
自有的方法
-无
继承的属性
-参阅Ember.StateManager
自有的属性
-initialState
默认值:'root'
说明:字符串。初始状态路径。
-location
默认值:'hash'
说明:字符串。用于管理应用的URL路由状态。支持以下属性值
'hash':使用URL的标识符(如#/blog/1)。
'history':使用浏览器的history.pushstate API。仅在支持pushstate的现代浏览器有效。
'none':不读取或设置浏览器的URL,但依旧允许路由转换。适合用于测试。
-rootURL
默认值:'/'
说明:字符串。在非根路径下时才使用。
事件
-参阅Ember.StateManager