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

posted @ 2012-11-23 22:48  Kiinlam  阅读(887)  评论(0编辑  收藏  举报