Ember.js 入門指南——路由定義
當你的應用啟動的時候,路由器就會匹配當前的URL到你定義的路由上。然後按照定義的路由層次逐個載入資料、設定應用程式狀態、渲染路由對應的模板。
1,基本路由
在app/router.js的map方法裡定義的路由會對映到當前的URL。當map方法被呼叫的時候方法體內的route方法就會建立路由。
下面使用Ember CLI命令建立兩個路由:
ember generate route about ember generate route favorites
命令執行完之後你可在你的專案目錄app/routes下面看到已經建立好的兩個路由檔案已經app/templates下面路由對應的模板檔案。
此時在app/router.js的map方法中已經存在了剛剛建立的路由配置。這個是Ember CLI自動為你建立了。
// app/router.js import Ember from 'ember'; import config from './config/environment'; var Router = Ember.Router.extend({ location: config.locationType }); Router.map(function() { this.route('about'); this.route('favorites'); }); export default Router;
現在分別修改app/templates下面的兩個模板檔案如下:
<!-- app/templates/about.hbs -->
這個是about模板!<br>
{{outlet}}
<!-- app/templates/favorites.hbs -->
這個是favorites模板!<br>
{{outlet}}
如果你覺得favorites這個路由名字太長是否可以修改成其他名字呢?答案是肯定的,你只要修改router.js中map方法的配置即可。
Router.map(function() { this.route('about'); // 注意:訪問的URL可以寫favs但是專案中如果是使用route的地方仍然是使用favorites this.route('favorites', { path: '/favs' }); });
說明:預設情況下訪問的URL與路由名字是一致的,比如“this.route('about')”與“this.route('about', { path: ‘/about’ })”是同一個路由,如果URL與路由不同名則需要使用{path: ‘/xxx’}設定對映的URL。
在handlebars模板中可以使用{{link-to}}助手在不同的路由間切換,使用時需要在link-to助手內指定路由名稱。比如下面的程式碼使用link-to助手實現在about和favs兩個路由間切換。
為了頁面能美觀一點引入bootstrap,使用npm命令安裝:bower install bootstrap,如果安裝成功你可以在bower_components目錄下看到bootstrap相關的檔案。安裝成功之後引入到專案中,修改chapter3_routes/ember-cli-build.js。在return語句前加入如下兩行程式碼(作用就是引入bootstrap框架):
app.import("bower_components/bootstrap/dist/css/bootstrap.css"); app.import("bower_components/bootstrap/dist/js/bootstrap.js");
修改application.hbs,增加一個導航選單。
<!-- //app/templates/application.hbs -->
<nav class="navbar navbar-inverse navbar-fixed-top">
<div>
<div href="#">
<!-- <a href="#">Blog</a> -->
{{#link-to 'index'}}Home{{/link-to}}
</div>
<ul class="nav navbar-nav">
<li>{{#link-to 'about'}}about{{/link-to}}</li>
<li>{{#link-to 'favorites'}}favorites{{/link-to}}</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li><a href="#">Login</a></li>
<li><a href="#">Logout</a></li>
</ul>
</div>
</nav>
<div style="margin-top: 70px;">
<!-- 專案中其他所有的模板都是application的子模板,所以其他模板都會渲染到這裡的 outlet上 -->
{{outlet}}
</div>
如果看到頁面沒有bootstrap效果請重新啟動專案。如果執行專案後再瀏覽器控制檯出現如下錯誤。
請在config/environment.js的APP後面新增如下內容:
, contentSecurityPolicy: { 'default-src': "'none'", 'script-src': "'self' 'unsafe-inline' 'unsafe-eval' use.typekit.net connect.facebook.net maps.googleapis.com maps.gstatic.com", 'font-src': "'self' data: use.typekit.net", 'connect-src': "'self'", 'img-src': "'self' www.facebook.com p.typekit.net", 'style-src': "'self' 'unsafe-inline' use.typekit.net", 'frame-src': "s-static.ak.facebook.com static.ak.facebook.com www.facebook.com" }
然後重啟專案再執行就不會報上面的錯誤了!!
如果你的程式沒有其他錯誤那麼你也會得到如下圖的結果介面:
然後點選“about”會得到如下介面
可以看到瀏覽器位址列的URL變為about了,並且頁面顯示的內容也是about模板的內容。同理你點選“favorites”位址列就變為http://localhost:4200/favs並且顯示的內容是favorites的(為什麼URL是favs而不是favorites呢,因為前面已經修改了route和URL的對映關係,路由favorites對應的URL是favs)。
上述演示的就是路由的切換!!!
2,路由巢狀
還記得在前面的《Ember.js 入門指南——{{link-to}} 助手》這篇文章的內容嗎?在這篇文章中比較詳細的介紹了路由的巢狀與怎麼使用巢狀的路由。不妨回過頭去看看。在這裡打算就不講了……如果有不明白的請看官網的教程。
3,application路由
application路由是預設的路由,是程式的入口,所有其他自定義的路由都先進過application才到自定義的路由。並且application路由對應的application.hbs模板是所有自定義模板的父模板,所有自定義的模板都會渲染到application.hbs模板的{{outlet}}上。有關於路由的執行順序以及模板的渲染順序在前面的《Ember.js 入門指南——{{link-to}} 助手》也講過了,在此也不打算在做過多的介紹了。你可以回頭看之前的文章或者到官網檢視。
4,index路由
對於所有的巢狀的路由,包括最頂層的路由Ember會自動生成一個訪問URL為“/”對應路由名稱為“index”的路由。
比如下面的兩種路由設定是等價的。
// app/router.js // …… Router.map(function() { this.route('about'); // 注意:訪問的URL可以寫favs但是專案中如果是使用route的地方仍然是使用favorites this.route('favorites', { path: '/favs' }); }); export default Router;
// app/router.js // …… Router.map(function() { this.route('index', { path: '/' }); this.route('about'); // 注意:訪問的URL可以寫favs但是專案中如果是使用route的地方仍然是使用favorites this.route('favorites', { path: '/favs' }); }); export default Router;
index路由會渲染到application.hbs模板的{{outlet}}上。這個是Ember預設設定。當用戶訪問“/about”時Ember會把index模板替換為about模板。
對於路由巢狀的情況也是如此。
// app/router.js // …… Router.map(function() { this.route('posts', function() { this.route('new'); }); }); export default Router;
// app/router.js // …… Router.map(function() { this.route('index', { path: '/' }); this.route('posts', function() { this.route('index', { path: '/' }); this.route('new'); }); });
兩種設定方式都會得到如下圖的路由表。開啟瀏覽器的“開發者工具”點開“Ember”選項卡,在點開“/#Routes”你就可以看到如下路由表(顯示是順序有可能跟你的不一樣)。
注:loading和error這兩個路由是ember自動生成的,他們的用法會在後面的文章介紹。
當用戶訪問“/posts”時實際進入的路由是posts.index對應的模板是posts/index.hbs,但是實際中我並沒有建立這個模板,因為Ember預設把這個模板渲染到posts.hbs的{{outlet}}上。由於這個模板不存在也就相當於什麼都沒做。當然你也可以建立這個模板。使用命令:ember generate template posts/index然後在這個模板中新增以下顯示的內容:
<!-- app/templates/posts/index.hbs -->
<h2>這裡是/posts/index.hbs。。。</h2>
你可以這麼理解對於每一個有子路由的路由都有一個名為index的子路由並且這個路由對應的模板為index.hbs,如果把有子路由的路由當做一個模組看待那麼index.hbs就是這個模組的首頁。特別是做過一些資訊系統的朋友應該是很熟悉的,基本上沒個子模組都會有一個首頁,這個首頁現實的內容就是一進入這個模組時就顯示的內容。既然是子模板當然也不會例外它也會渲染到父模板的{{outlet}}上。比如上面的例子當用戶訪問http://localhost:4200/posts實際進入的是http://localhost:4200/posts/(後面多了一個“/”,這個“/”對應的模板就是index),當用戶訪問的是http://localhost:4200/posts/new,那麼進入的就是posts/new.hbs這個模板(也是渲染到posts.hbs的{{outlet}}上)。
4,動態段
路由最主要的任務之一就是載入model。
例如對於路由this.route(“posts”);會載入專案中所有的posts下的model。但是當你只想載入其中一個model的時候怎麼處理呢?而且大多數情況我們是不需要一次性載入完全部資料的,一般情況都是載入其中一小部分。這個時候就需要動態段了!
動態段以“:”開頭,並且後面接著model的id屬性。
// app/router.js // …… Router.map(function() { this.route('about'); // 注意:訪問的URL可以寫favs但是專案中如果是使用route的地方仍然是使用favorites // this.route('favorites', { path: '/favs' }); this.route('posts', function() { this.route('post', { path: '/:post_id'}); }); }); export default Router;
5,萬用字元/全域性路由
Ember也同樣執行你使用“*”作為URL萬用字元。有了萬用字元你可以設定多個URL訪問同一個路由。
this.route('about', { path: '/*wildcard' });
6,重置子路由的名稱空間
在有路由巢狀的情況下,一般情況我們訪問URL的格式都是“父路由名/子路由名”,Ember提供了一個“resetNamespace:true”選項可以使用者重置子路由的名稱空間,使用這個設定的路由可以直接這樣訪問“/子路由名”,不需要寫父路由名。
this.route('posts', function() { this.route('post', { path: '/:post_id'}); this.route('comments', { resetNamespace: true}, function() { this.route('new'); }); });
不過個人覺得還是不使用這個設定比較好,特別是在開發的時候你可以看到訪問的URL的層次,對你除錯程式碼還是很有幫助的。
以上的內容就是定義路由的全部內容。都是非常重要的知識,希望你能好好掌握,對於路由的巢狀請看之前的文章。如果有疑問請給我留言或者訪問官網看原教程。