#2 定義路由

英文原版:https://guides.emberjs.com/v2.13.0/routing/defining-your-routes/

當你開始運行你的app時,router會將當前的URL與你定義路由相匹配。這些路由呢,則會負責顯示模板,讀取數據並且更新app狀態。

定義路由,命令:

ember generate route route-name

這個命令創建了個一個路由源文件:app/routes/route-name.js,一個模板文件:app/templates/route-name.hbs和一個單元測試文件:tests/unit/routes/route-name-test.js。並且會在app/router.js中添加一條路由信息。

基本路由

Ember應用的app/router.js中的map()方法會被調用,用來生成路由映射。當調用map()時,你需要給它傳一個函數,並且在函數內需要通過this.route()來定義路由。

app/router.js

Router.map(function() {
  this.route('about', { path: '/about' });
  this.route('favorites', { path: '/favs' });
});

好了,現在如果用戶訪問 /about 路由,Ember將會渲染about模板;若訪問/favs,則會渲染 favorites 模板。

當然如果路由名稱與名稱對象的值一樣,你也可以不設置名稱對象。下面的這個種方式與上面的例子是等價的:

app/router.js

Router.map(function() {
  this.route('about');
  this.route('favorites', { path: '/favs' });
});

在模板中,你可以使用{{link-to}}助手來在這這些路由之間進行導航。助手中的路由參數值,只需要跟你在router中定義的router()方法的第一各參數一致即可:

{{#link-to "index"}}<img class="logo">{{/link-to}}

<nav>
  {{#link-to "about"}}About{{/link-to}}
  {{#link-to "favorites"}}Favorites{{/link-to}}
</nav>

當然,你可以在{{link-to}}助手中添加一個active類,用來標示當前正在訪問的路由。

多詞名稱路由,需要你用減號來作爲每個單詞的分隔符:

app/router.js

Router.map(function() {
  this.route('blog-post', { path: '/blog-post' });
});

上面定義的這個路由,默認會使用blog-post.js作爲它的處理程序,blog-post.hbs作爲模板,並且在{{link-to}}助手中通過blog-post來引用。

你可以可以使用下面這種方式來命名多詞路由:

app/router.js

Router.map(function() {
  this.route('blog_post', { path: '/blog-post' });
});

這種方式仍然會以blog-post.js作爲它的處理程序、blog-post.hbs作爲模板。但是,在{{link-to}}助手中需要使用blog_post來引用

嵌套路由

你嚐嚐也會需要使模板可以顯示它下層的其他模板。比如,在一個博客應用中,相對於在 一堆的博客列表中有個創建博客的區域,或許你更傾向於在列表頁的下一頁專門弄個創建博客的頁面。

這個時候,嵌套路由就用上了。

定義嵌套路由只需要在this.route中添加一個回調函數:

app/router.js

Router.map(function() {
  this.route('posts', function() {
    this.route('new');
  });
});

這裏假設你已經生成了post路由,爲了生成它的嵌套路由,你可以運行下面的命令:

ember generate route posts/new

然後,在post路由中放一個 {{outlet}},用來在上層路由中顯示嵌套路由:

templates/posts.hbs

<h1>Posts</h1>
<!-- Display posts and other content -->
{{outlet}}

router會創建一個/posts映射和一個/posts/new映射。當用戶訪問/posts時,他們只會看見posts.hbs模板中的內容(注意了,回憶下之前說過的index路由)。只有當用戶訪問posts/new時,posts/new.hbs模板纔會被渲染並出現在{{outlet}}所在位置,緊接着纔會在頁面上出現。

嵌套路由的名字中包含它的祖先路由的名字。如果你想跳轉到其他路由(通過transitionTo或{{#link-to}}實現挑破轉),請確保使用完整的路由名稱,例如: 使用posts.new 而不是new

application路由

當你的應用第一次啓動的時候,那麼將會首先進入application路由。如果其他路由一樣,所讀取的模板也是application。你可以將你的網站的header,footer或者其他始終顯示在頁面的內容放在application.hbs中。其他路由的模板將會最終將會被渲染到application.hbs模板的{{outlet}}中。

application路由是每個Ember應用的固定一部分,所以你不需要再app/router.js人爲的去設置它。

Index路由

在嵌套路由的每一層(包括最頂層路由),Ember會自動的提供一個路由映射到 “/”,並且命名爲index。如果你想了解在哪層有嵌套,打開router,如果你在this.route()中看到了一個function(){},那麼這裏是嵌套。

比如,你寫了個簡單的路由:

app/router.js

Router.map(function() {
  this.route('favorites');
});

它等價於:

app/router.js

Router.map(function() {
  this.route('index', { path: '/' });
  this.route('favorites');
});

index模板將會被渲染到application模板的{{outlet}}中,如果用戶導航到/favorites,Ember將會用favorites模板替換掉index模板。

嵌套路由長這樣:

app/router.js

Router.map(function() {
  this.route('posts', function() {
    this.route('favorites');
  });
});

上面的定義等價於:

app/router.js

Router.map(function() {
  this.route('index', { path: '/' });
  this.route('posts', function() {
    this.route('index', { path: '/' });
    this.route('favorites');
  });
});

如果用戶導航到/posts,那麼當前的路由會是posts.index,並且posts.index模板將會被渲染到posts模板的{{outlet}}中。

如果用戶接着又導航到/posts/favorites,Ember會將posts/favorites模板渲染,然後用它代替index模板。

動態段

路由負責的事情之一是讀取模型數據。

比如,我們現在有個路由:this.route(‘posts’),那麼這個路由弄不好會把所有的帖子都讀取過來。

這是因爲/posts代表了一個固定的模型,我們沒有添加可以讓它進行檢索的附加信息。然而,如果我們需要一個僅代表某一個帖子的路由,我們就不能再路由中以這樣的形式硬編碼了。

動態段是URL的一部分,以”:”冒號開始,以一個標識符結束:

app/router.js

Router.map(function() {
  this.route('posts');
  this.route('post', { path: '/post/:post_id' });
});

這個時候,如果用戶導航到/post/5,那麼路由將會將5代替post_id從而讀取到對應的那個帖子。Ember遵守這個約定(:model-name_id)出於2個目的:

  1. 如果你遵從這個約定,那麼路由將會明白如何拉去正確的模型數據。
  2. params是一個對象,並且一個key只能關聯一個值。

將以下形式用於代碼中,將不會正確運行:

app/router.js

Router.map(function() {
  this.route('photo', { path: '/photo/:id' }, function() {
    this.route('comment', { path: '/comment/:id' });
  });
});

但是下面這樣可以:

app/router.js

Router.map(function() {
  this.route('photo', { path: '/photo/:photo_id' }, function() {
    this.route('comment', { path: '/comment/:comment_id' });
  });
});

通配符/全局路由

你可以定義通配符路由用以匹配多個URL動態段。你可以這麼用,比如,當用戶進入了某些不存在於你app的URL,那麼你可以通過通配符路由來捕捉所有的這些不存在的URL。通配符路由以星號開頭:

app/router.js

Router.map(function() {
  this.route('not-found', { path: '/*path' });
});
app/templates/not-found.hbs

<p>Oops, the page you're looking for wasn't found</p>

在上面的例子中,我們成功了處理了對應用中不存在的URL的訪問,所以當用戶導航到一個不存在的路徑的**path路徑的時候,就會給他顯示一個提示信息。

路由處理程序

爲了讓路由在模板渲染之前做些什麼,你需要創建一個路由處理程序。本章後續的教程中會陸續向你揭示路由處理程序的各種功用。更多關於路由信息,詳見API文檔:the routerroute handlers

本節完

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章