Ember 路由定義

2018-01-06 17:47 更新

當(dāng)你的應(yīng)用啟動(dòng)的時(shí)候,路由器就會(huì)匹配當(dāng)前的URL到你定義的路由上。然后按照定義的路由層次逐個(gè)加載數(shù)據(jù)、設(shè)置應(yīng)用程序狀態(tài)、渲染路由對(duì)應(yīng)的模板。

1,基本路由

app/router.jsmap方法里定義的路由會(huì)映射到當(dāng)前的URL。當(dāng)map方法被調(diào)用的時(shí)候方法體內(nèi)的route方法就會(huì)創(chuàng)建路由。

下面使用Ember CLI命令創(chuàng)建兩個(gè)路由:

ember generate route about
ember generate route favorites

命令執(zhí)行完之后你可在你的項(xiàng)目目錄app/routes下面看到已經(jīng)創(chuàng)建好的兩個(gè)路由文件已經(jīng)app/templates下面路由對(duì)應(yīng)的模板文件。 此時(shí)在app/router.jsmap方法中已經(jīng)存在了剛剛創(chuàng)建的路由配置。這個(gè)是Ember CLI自動(dòng)為你創(chuàng)建了。

// 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;

現(xiàn)在分別修改app/templates下面的兩個(gè)模板文件如下:





這個(gè)是about模板!<br>
{{outlet}}




這個(gè)是favorites模板!<br>
{{outlet}}

然后訪問(wèn)http://localhost:4200/about或者http://localhost:4200/favorites,如果你的程序沒(méi)有問(wèn)題你也會(huì)得到如下顯示結(jié)果:

run result

如果你覺(jué)得favorites這個(gè)路由名字太長(zhǎng)是否可以修改成其他名字呢?答案是肯定的,你只要修改router.jsmap方法的配置即可。

Router.map(function() {
  this.route('about');
  // 注意:訪問(wèn)的URL可以寫(xiě)favs但是項(xiàng)目中如果是使用route的地方仍然是使用favorites
  this.route('favorites', { path: '/favs' });
});

此時(shí)訪問(wèn):http://localhost:4200/favs,界面顯示的結(jié)果與之前是一樣的。

說(shuō)明:默認(rèn)情況下訪問(wèn)的URL與路由名字是一致的,比如this.route('about')this.route('about', { path: ‘/about’ })是同一個(gè)路由,如果URL與路由不同名則需要使用{path: '/xxx'}設(shè)置映射的URL。

在handlebars模板中可以使用{{link-to}}助手在不同的路由間切換,使用時(shí)需要在link-to助手內(nèi)指定路由名稱(chēng)。比如下面的代碼使用link-to助手實(shí)現(xiàn)在aboutfavs兩個(gè)路由間切換。 為了頁(yè)面能美觀一點(diǎn)引入bootstrap,使用npm命令安裝:bower install bootstrap,如果安裝成功你可以在bower_components目錄下看到bootstrap相關(guān)的文件。安裝成功之后引入到項(xiàng)目中,修改chapter3_routes/ember-cli-build.js。在return語(yǔ)句前加入如下兩行代碼(作用就是引入bootstrap框架):

app.import("bower_components/bootstrap/dist/css/bootstrap.css");
app.import("bower_components/bootstrap/dist/js/bootstrap.js");

修改application.hbs,增加一個(gè)導(dǎo)航菜單。







    <div class="container-fluid">
            <div class="navbar-header" href="#">

                
                {{#link-to 'index' class="navbar-brand"}}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>




<div class="container-fluid" style="margin-top: 70px;">


{{outlet}}
</div>

如果看到頁(yè)面沒(méi)有bootstrap效果請(qǐng)重新啟動(dòng)項(xiàng)目。如果運(yùn)行項(xiàng)目后再瀏覽器控制臺(tái)出現(xiàn)如下錯(cuò)誤。

run result

如果出現(xiàn)上圖錯(cuò)誤需要在config/environment.js中加上一些安全策略設(shè)置代碼,有關(guān)設(shè)置的解釋請(qǐng)看下面網(wǎng)址的文章介紹。

  1. ember-cli-and-content-security-policy-cs
  2. https://www.w3.org/TR/2015/CR-CSP2-20150721/
    , 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"
    }

配置截圖

上圖是我的演示項(xiàng)目配置。然后點(diǎn)擊about會(huì)得到如下界面

result

可以看到瀏覽器地址欄的URL變?yōu)?code>about了,并且頁(yè)面顯示的內(nèi)容也是about模板的內(nèi)容。同理你點(diǎn)擊favorites地址欄就變?yōu)?a href="http://localhost:4200/favs" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" >http://localhost:4200/favs并且顯示的內(nèi)容是favorites的(為什么URL是favs而不是favorites呢,因?yàn)榍懊嬉呀?jīng)修改了route和URL的映射關(guān)系,路由favorites對(duì)應(yīng)的URL是favs)。 上述演示的就是路由的切換?。?!

可以看到瀏覽器地址欄的URL變?yōu)閍bout了,并且頁(yè)面顯示的內(nèi)容也是about模板的內(nèi)容。同理你點(diǎn)擊“favorites”地址欄就變?yōu)閔ttp://localhost:4200/favs并且顯示的內(nèi)容是favorites的(為什么URL是favs而不是favorites呢,因?yàn)榍懊嬉呀?jīng)修改了route和URL的映射關(guān)系,路由favorites對(duì)應(yīng)的URL是favs)。 上述演示的就是路由的切換?。?!

2,路由嵌套

還記得在前面的Ember.js 入門(mén)指南之十三{{link-to}} 助手這篇文章的內(nèi)容嗎?在這篇文章中比較詳細(xì)的介紹了路由的嵌套與怎么使用嵌套的路由。不妨回過(guò)頭去看看。在這里打算就不講了……如果有不明白的請(qǐng)看官網(wǎng)的教程。

3,application路由

application路由是默認(rèn)的路由,是程序的入口,所有其他自定義的路由都先進(jìn)過(guò)application才到自定義的路由。并且application路由對(duì)應(yīng)的application.hbs模板是所有自定義模板的父模板,所有自定義的模板都會(huì)渲染到application.hbs模板的{{outlet}}上。有關(guān)于路由的執(zhí)行順序以及模板的渲染順序在前面的Ember.js 入門(mén)指南之十三{{link-to}} 助手也講過(guò)了,在此也不打算在做過(guò)多的介紹了。你可以回頭看之前的文章或者到官網(wǎng)查看。

4,index路由

對(duì)于所有的嵌套的路由,包括最頂層的路由Ember會(huì)自動(dòng)生成一個(gè)訪問(wèn)URL為/對(duì)應(yīng)路由名稱(chēng)為index的路由。

比如下面的兩種路由設(shè)置是等價(jià)的。

//  app/router.js
// ……


Router.map(function() {
    this.route('about');
    // 注意:訪問(wèn)的URL可以寫(xiě)favs但是項(xiàng)目中如果是使用route的地方仍然是使用favorites
    this.route('favorites', { path: '/favs' });
});


export default Router;

//  app/router.js
// ……


Router.map(function() {
    this.route('index', { path: '/' });
    this.route('about');
    // 注意:訪問(wèn)的URL可以寫(xiě)favs但是項(xiàng)目中如果是使用route的地方仍然是使用favorites
    this.route('favorites', { path: '/favs' });
});


export default Router;

index路由會(huì)渲染到application.hbs模板的{{outlet}}上。這個(gè)是Ember默認(rèn)設(shè)置。當(dāng)用戶(hù)訪問(wèn)/about時(shí)Ember會(huì)把index模板替換為about模板。

對(duì)于路由嵌套的情況也是如此。

//  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');
    });


});


export default Router;

兩種設(shè)置方式都會(huì)得到如下圖的路由表。打開(kāi)瀏覽器的“開(kāi)發(fā)者工具”點(diǎn)開(kāi)“Ember”選項(xiàng)卡,在點(diǎn)開(kāi)“/#Routes”你就可以看到如下路由表(顯示是順序有可能跟你的不一樣)。

路由渲染結(jié)果

注:loadingerror這兩個(gè)路由是ember自動(dòng)生成的,他們的用法會(huì)在后面的文章介紹。

當(dāng)用戶(hù)訪問(wèn)/posts時(shí)實(shí)際進(jìn)入的路由是posts.index對(duì)應(yīng)的模板是posts/index.hbs,但是實(shí)際中我并沒(méi)有創(chuàng)建這個(gè)模板,因?yàn)镋mber默認(rèn)把這個(gè)模板渲染到posts.hbs{{outlet}}上。由于這個(gè)模板不存在也就相當(dāng)于什么都沒(méi)做。當(dāng)然你也可以創(chuàng)建這個(gè)模板。
使用命令:ember generate template posts/index然后在這個(gè)模板中添加以下顯示的內(nèi)容:





<h2>這里是/posts/index.hbs。。。</h2>

再此訪問(wèn)http://localhost:4200/posts,是不是可以看到增加的內(nèi)容了。

你可以這么理解對(duì)于每一個(gè)有子路由的路由都有一個(gè)名為index的子路由并且這個(gè)路由對(duì)應(yīng)的模板為index.hbs,如果把有子路由的路由當(dāng)做一個(gè)模塊看待那么index.hbs就是這個(gè)模塊的首頁(yè)。特別是做過(guò)一些信息系統(tǒng)的朋友應(yīng)該是很熟悉的,基本上沒(méi)個(gè)子模塊都會(huì)有一個(gè)首頁(yè),這個(gè)首頁(yè)現(xiàn)實(shí)的內(nèi)容就是一進(jìn)入這個(gè)模塊時(shí)就顯示的內(nèi)容。既然是子模板當(dāng)然也不會(huì)例外它也會(huì)渲染到父模板的{{outlet}}上。比如上面的例子當(dāng)用戶(hù)訪問(wèn)http://localhost:4200/posts實(shí)際進(jìn)入的是http://localhost:4200/posts/(后面多了一個(gè)/,這個(gè)/對(duì)應(yīng)的模板就是index),當(dāng)用戶(hù)訪問(wèn)的是http://localhost:4200/posts/new,那么進(jìn)入的就是posts/new.hbs這個(gè)模板(也是渲染到posts.hbs{{outlet}}上)。

4,動(dòng)態(tài)段

關(guān)于動(dòng)態(tài)段在前面的Ember.js 入門(mén)指南之十三{{link-to}} 助手也介紹過(guò)了,在這里就再簡(jiǎn)單補(bǔ)充下。

路由最主要的任務(wù)之一就是加載model。

例如對(duì)于路由this.route('posts');會(huì)加載項(xiàng)目中所有的posts下的model。但是當(dāng)你只想加載其中一個(gè)model的時(shí)候怎么處理呢?而且大多數(shù)情況我們是不需要一次性加載完全部數(shù)據(jù)的,一般情況都是加載其中一小部分。這個(gè)時(shí)候就需要?jiǎng)討B(tài)段了!

動(dòng)態(tài)段以:開(kāi)頭,并且后面接著modelid屬性。

//  app/router.js


//  ……


Router.map(function() {
    this.route('about');
    // 注意:訪問(wèn)的URL可以寫(xiě)favs但是項(xiàng)目中如果是使用route的地方仍然是使用favorites
    // this.route('favorites', { path: '/favs' });


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

    
});


export default Router;

此時(shí)你可以訪問(wèn)http://localhost:4200/posts/1,不過(guò)我們還沒(méi)創(chuàng)建model所以會(huì)報(bào)錯(cuò)。這個(gè)我們暫時(shí)不管,后面會(huì)有一章是介紹model的?,F(xiàn)在只要知道你訪問(wèn)http://localhost:4200/posts/1就相當(dāng)于獲取id值唯一的model。

5,通配符/全局路由

Ember也同樣運(yùn)行你使用*作為URL通配符。有了通配符你可以設(shè)置多個(gè)URL訪問(wèn)同一個(gè)路由。

this.route('about', { path: '/*wildcard' });

然后訪問(wèn):http://localhost:4200/wildcard或者訪問(wèn)http://localhost:4200/2423432ffasdfewildcard或者http://localhost:4200/2333都是可以進(jìn)入到about這個(gè)路由,但是http://localhost:4200/posts仍然進(jìn)入的是posts這個(gè)路由。因?yàn)榭梢云ヅ涞竭@個(gè)路由。

6,重置子路由的命名空間

在有路由嵌套的情況下,一般情況我們?cè)L問(wèn)URL的格式都是父路由名/子路由名,Ember提供了一個(gè)resetNamespace:true選項(xiàng)可以用戶(hù)重置子路由的命名空間,使用這個(gè)設(shè)置的路由可以直接這樣訪問(wèn)/子路由名,不需要寫(xiě)父路由名。

this.route('posts', function() {
    this.route('post', { path: '/:post_id'});
    this.route('comments', { resetNamespace: true}, function() {
        this.route('new');
    });
});

此時(shí)如果你想問(wèn)的new這個(gè)路由你可以直接不寫(xiě)comments。http://localhost:4200/posts/new,而不需要http://localhost:4200/posts/comments/new,不過(guò)模板渲染的順序沒(méi)變,new模板仍然是渲染到comments{{outlet}}上。

不過(guò)個(gè)人覺(jué)得還是不使用這個(gè)設(shè)置比較好,特別是在開(kāi)發(fā)的時(shí)候你可以看到訪問(wèn)的URL的層次,對(duì)你調(diào)試代碼還是很有幫助的。

以上的內(nèi)容就是定義路由的全部?jī)?nèi)容。都是非常重要的知識(shí),希望你能好好掌握,對(duì)于路由的嵌套請(qǐng)看之前的文章。如果有疑問(wèn)請(qǐng)給我留言或者訪問(wèn)官網(wǎng)看原教程。
博文完整代碼放在Github(博文經(jīng)過(guò)多次修改,博文上的代碼與github代碼可能又出入,不過(guò)影響不大?。?,如果你覺(jué)得博文對(duì)你有點(diǎn)用,請(qǐng)?jiān)趃ithub項(xiàng)目上給我點(diǎn)個(gè)star吧。您的肯定對(duì)我來(lái)說(shuō)是最大的動(dòng)力??!

以上內(nèi)容是否對(duì)您有幫助:
在線(xiàn)筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)