Angular 常見(jiàn)路由任務(wù)

2022-07-01 15:13 更新

常見(jiàn)路由任務(wù)

本主題講述當(dāng)把 Angular 路由器添加到應(yīng)用中時(shí),如何實(shí)現(xiàn)多種常見(jiàn)路由任務(wù)。

生成一個(gè)支持路由的應(yīng)用

下面的命令會(huì)用 Angular CLI 來(lái)生成一個(gè)帶有應(yīng)用路由模塊(?AppRoutingModule?)的基本 Angular 應(yīng)用,它是一個(gè) NgModule,可用來(lái)配置路由。下面的例子中應(yīng)用的名字是 ?routing-app?。

ng new routing-app --routing --defaults

為路由添加組件

為了使用 Angular 的路由器,應(yīng)用至少要有兩個(gè)組件才能從一個(gè)導(dǎo)航到另一個(gè)。要使用 CLI 創(chuàng)建組件,請(qǐng)?jiān)诿钚休斎胍韵聝?nèi)容,其中 ?first ?是組件的名稱:

ng generate component first

為第二個(gè)組件重復(fù)這個(gè)步驟,但給它一個(gè)不同的名字。這里的新名字是 ?second?。

ng generate component second

CLI 會(huì)自動(dòng)添加 ?Component ?后綴,所以如果在編寫 ?first-component?,那么其組件名就是 ?FirstComponentComponent?。

<base href>
本指南適用于 CLI 生成的 Angular 應(yīng)用。如果你是手動(dòng)工作的,請(qǐng)確保你的 index.html 文件的 ?<head>? 中有 ?<base href="/">? 語(yǔ)句。這里假定 ?app ?文件夾是應(yīng)用的根目錄,并使用 ?"/"? 作為基礎(chǔ)路徑。

導(dǎo)入這些新組件

要使用這些新組件,請(qǐng)把它們導(dǎo)入到該文件頂部的 ?AppRoutingModule ?中,具體如下:

import { FirstComponent } from './first/first.component';
import { SecondComponent } from './second/second.component';

定義一個(gè)基本路由

創(chuàng)建路由有三個(gè)基本的構(gòu)建塊。

把 ?AppRoutingModule ?導(dǎo)入 ?AppModule ?并把它添加到 ?imports ?數(shù)組中。

Angular CLI 會(huì)為你執(zhí)行這一步驟。但是,如果要手動(dòng)創(chuàng)建應(yīng)用或使用現(xiàn)存的非 CLI 應(yīng)用,請(qǐng)驗(yàn)證導(dǎo)入和配置是否正確。下面是使用 ?--routing? 標(biāo)志生成的默認(rèn) ?AppModule?。

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module'; // CLI imports AppRoutingModule
import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule // CLI adds AppRoutingModule to the AppModule's imports array
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
  1. 把 ?RouterModule ?和 ?Routes ?導(dǎo)入到你的路由模塊中。
  2. Angular CLI 會(huì)自動(dòng)執(zhí)行這一步驟。CLI 還為你的路由設(shè)置了 ?Routes ?數(shù)組,并為 ?@NgModule()? 配置了 ?imports ?和 ?exports ?數(shù)組。

    import { NgModule } from '@angular/core';
    import { Routes, RouterModule } from '@angular/router'; // CLI imports router
    
    const routes: Routes = []; // sets up routes constant where you define your routes
    
    // configures NgModule imports and exports
    @NgModule({
      imports: [RouterModule.forRoot(routes)],
      exports: [RouterModule]
    })
    export class AppRoutingModule { }
  3. 在 ?Routes ?數(shù)組中定義你的路由。
  4. 這個(gè)數(shù)組中的每個(gè)路由都是一個(gè)包含兩個(gè)屬性的 JavaScript 對(duì)象。第一個(gè)屬性 ?path ?定義了該路由的 URL 路徑。第二個(gè)屬性 ?component ?定義了要讓 Angular 用作相應(yīng)路徑的組件。

    const routes: Routes = [
      { path: 'first-component', component: FirstComponent },
      { path: 'second-component', component: SecondComponent },
    ];
  5. 把這些路由添加到你的應(yīng)用中。
  6. 現(xiàn)在你已經(jīng)定義了路由,可以把它們添加到應(yīng)用中了。首先,添加到這兩個(gè)組件的鏈接。把要添加路由的鏈接賦值給 ?routerLink ?屬性。將屬性的值設(shè)置為該組件,以便在用戶點(diǎn)擊各個(gè)鏈接時(shí)顯示這個(gè)值。接下來(lái),修改組件模板以包含 ?<router-outlet>? 標(biāo)簽。該元素會(huì)通知 Angular,你可以用所選路由的組件更新應(yīng)用的視圖。

    <h1>Angular Router App</h1>
    <!-- This nav gives you links to click, which tells the router which route to use (defined in the routes constant in  AppRoutingModule) -->
    <nav>
      <ul>
        <li><a routerLink="/first-component" routerLinkActive="active">First Component</a></li>
        <li><a routerLink="/second-component" routerLinkActive="active">Second Component</a></li>
      </ul>
    </nav>
    <!-- The routed views render in the <router-outlet>-->
    <router-outlet></router-outlet>

路由順序

路由的順序很重要,因?yàn)?nbsp;?Router ?在匹配路由時(shí)使用“先到先得”策略,所以應(yīng)該在不那么具體的路由前面放置更具體的路由。首先列出靜態(tài)路徑的路由,然后是一個(gè)與默認(rèn)路由匹配的空路徑路由。通配符路由是最后一個(gè),因?yàn)樗ヅ涿恳粋€(gè) URL,只有當(dāng)其它路由都沒(méi)有匹配時(shí),?Router ?才會(huì)選擇它。

獲取路由信息

通常,當(dāng)用戶導(dǎo)航你的應(yīng)用時(shí),你會(huì)希望把信息從一個(gè)組件傳遞到另一個(gè)組件。例如,考慮一個(gè)顯示雜貨商品購(gòu)物清單的應(yīng)用。列表中的每一項(xiàng)都有一個(gè)唯一的 ?id?。要想編輯某個(gè)項(xiàng)目,用戶需要單擊“編輯”按鈕,打開(kāi)一個(gè) ?EditGroceryItem ?組件。你希望該組件得到該商品的 ?id?,以便它能向用戶顯示正確的信息。

可以用一個(gè)路由把這種類型的信息傳給你的應(yīng)用組件。要做到這一點(diǎn),你可以使用 ?ActivatedRoute ?接口。

要從路由中獲取信息:

  1. 把 ?ActivatedRoute ?和 ?ParamMap ?導(dǎo)入你的組件。
  2. import { Router, ActivatedRoute, ParamMap } from '@angular/router';

    這些 import 語(yǔ)句添加了組件所需的幾個(gè)重要元素。

  3. 通過(guò)把 ?ActivatedRoute ?的一個(gè)實(shí)例添加到你的應(yīng)用的構(gòu)造函數(shù)中來(lái)注入它:
  4. constructor(
      private route: ActivatedRoute,
    ) {}
  5. 更新 ?ngOnInit()? 方法來(lái)訪問(wèn)這個(gè) ?ActivatedRoute ?并跟蹤 ?name ?參數(shù):
  6. ngOnInit() {
      this.route.queryParams.subscribe(params => {
        this.name = params['name'];
      });
    }

    注意:前面的例子使用了一個(gè)變量 ?name?,并根據(jù) ?name ?參數(shù)給它賦值。

設(shè)置通配符路由

當(dāng)用戶試圖導(dǎo)航到那些不存在的應(yīng)用部件時(shí),在正常的應(yīng)用中應(yīng)該能得到很好的處理。要在應(yīng)用中添加此功能,需要設(shè)置通配符路由。當(dāng)所請(qǐng)求的 URL 與任何路由器路徑都不匹配時(shí),Angular 路由器就會(huì)選擇這個(gè)路由。

要設(shè)置通配符路由,請(qǐng)?jiān)?nbsp;?routes ?定義中添加以下代碼。

{ path: '**', component:  }

這兩個(gè)星號(hào) ?**? 告訴 Angular,這個(gè) ?routes ?定義是通配符路由。對(duì)于 component 屬性,你可以使用應(yīng)用中的任何組件。常見(jiàn)的選擇包括應(yīng)用專屬的 ?PageNotFoundComponent?,你可以定義它來(lái)向用戶展示 404 頁(yè)面,或者跳轉(zhuǎn)到應(yīng)用的主組件。通配符路由是最后一個(gè)路由,因?yàn)樗ヅ渌械?nbsp;URL。

顯示 404 頁(yè)面

要顯示 404 頁(yè)面,請(qǐng)?jiān)O(shè)置一個(gè)通配符路由,并將 ?component ?屬性設(shè)置為你要用于 404 頁(yè)面的組件,如下所示:

const routes: Routes = [
  { path: 'first-component', component: FirstComponent },
  { path: 'second-component', component: SecondComponent },
  { path: '**', component: PageNotFoundComponent },  // Wildcard route for a 404 page
];

?path ?為 ?**? 的最后一條路由是通配符路由。如果請(qǐng)求的 URL 與前面列出的路徑不匹配,路由器會(huì)選擇這個(gè)路由,并把該用戶送到 ?PageNotFoundComponent?。

設(shè)置重定向

要設(shè)置重定向,請(qǐng)使用重定向源的 ?path?、要重定向目標(biāo)的 ?component ?和一個(gè) ?pathMatch ?值來(lái)配置路由,以告訴路由器該如何匹配 URL。

const routes: Routes = [
  { path: 'first-component', component: FirstComponent },
  { path: 'second-component', component: SecondComponent },
  { path: '',   redirectTo: '/first-component', pathMatch: 'full' }, // redirect to `first-component`
  { path: '**', component: PageNotFoundComponent },  // Wildcard route for a 404 page
];

在這個(gè)例子中,第三個(gè)路由是重定向路由,所以路由器會(huì)默認(rèn)跳到 ?first-component? 路由。注意,這個(gè)重定向路由位于通配符路由之前。這里的 ?path: ''? 表示使用初始的相對(duì) URL( ?''? )。

嵌套路由

隨著你的應(yīng)用變得越來(lái)越復(fù)雜,你可能要?jiǎng)?chuàng)建一些根組件之外的相對(duì)路由。這些嵌套路由類型稱為子路由。這意味著你要為你的應(yīng)用添加第二 ?<router-outlet>?,因?yàn)樗?nbsp;?AppComponent ?之外的另一個(gè) ?<router-outlet>?。

在這個(gè)例子中,還有兩個(gè)子組件,?child-a? 和 ?child-b?。這里的 ?FirstComponent ?有它自己的 ?<nav>? 和 ?AppComponent ?之外的第二 ?<router-outlet>?。

<h2>First Component</h2>

<nav>
  <ul>
    <li><a routerLink="child-a">Child A</a></li>
    <li><a routerLink="child-b">Child B</a></li>
  </ul>
</nav>

<router-outlet></router-outlet>

子路由和其它路由一樣,同時(shí)需要 ?path ?和 ?component?。唯一的區(qū)別是你要把子路由放在父路由的 ?children ?數(shù)組中。

const routes: Routes = [
  {
    path: 'first-component',
    component: FirstComponent, // this is the component with the <router-outlet> in the template
    children: [
      {
        path: 'child-a', // child route path
        component: ChildAComponent, // child route component that the router renders
      },
      {
        path: 'child-b',
        component: ChildBComponent, // another child route component that the router renders
      },
    ],
  },
];

使用相對(duì)路徑

相對(duì)路徑允許你定義相對(duì)于當(dāng)前 URL 段的路徑。下面的例子展示了到另一個(gè)組件 ?second-component? 的相對(duì)路由。?FirstComponent ?和 ?SecondComponent ?在樹(shù)中處于同一級(jí)別,但是,指向 ?SecondComponent ?的鏈接位于 ?FirstComponent ?中,這意味著路由器必須先上升一個(gè)級(jí)別,然后進(jìn)入二級(jí)目錄才能找到 ?SecondComponent?。可以用 ?../? 符號(hào)來(lái)上升一個(gè)級(jí)別,而不用寫出到 ?SecondComponent ?的完整路徑。

<h2>First Component</h2>

<nav>
  <ul>
    <li><a routerLink="../second-component">Relative Route to second component</a></li>
  </ul>
</nav>
<router-outlet></router-outlet>

除了 ?../?,還可以使用 ?./? 或者不帶前導(dǎo)斜杠來(lái)指定當(dāng)前級(jí)別。

指定相對(duì)路由

要指定相對(duì)路由,請(qǐng)使用 ?NavigationExtras ?中的 ?relativeTo? 屬性。在組件類中,從 ?@angular/router? 導(dǎo)入 ?NavigationExtras?。

然后在導(dǎo)航方法中使用 ?relativeTo? 參數(shù)。在鏈接參數(shù)數(shù)組(它包含 ?items?)之后添加一個(gè)對(duì)象,把該對(duì)象的 ?relativeTo ?屬性設(shè)置為當(dāng)前的 ?ActivatedRoute?,也就是 ?this.route?。

goToItems() {
  this.router.navigate(['items'], { relativeTo: this.route });
}

?goToItems()? 方法會(huì)把目標(biāo) URI 解釋為相對(duì)于當(dāng)前路由的,并導(dǎo)航到 ?items ?路由。

訪問(wèn)查詢參數(shù)和片段

有時(shí),應(yīng)用中的某個(gè)特性需要訪問(wèn)路由的部件,比如查詢參數(shù)或片段(fragment)。本教程的這個(gè)階段使用了一個(gè)“英雄之旅”中的列表視圖,你可以在其中點(diǎn)擊一個(gè)英雄來(lái)查看詳情。路由器使用 ?id ?來(lái)顯示正確的英雄的詳情。

首先,在要導(dǎo)航的組件中導(dǎo)入以下成員。

import { ActivatedRoute } from '@angular/router';
import { Observable } from 'rxjs';
import { switchMap } from 'rxjs/operators';

接下來(lái),注入當(dāng)前路由(ActivatedRoute)服務(wù):

constructor(private route: ActivatedRoute) {}

配置這個(gè)類,讓你有一個(gè)可觀察對(duì)象 ?heroes$?、一個(gè)用來(lái)保存英雄的 ?id ?號(hào)的 ?selectedId?,以及 ?ngOnInit()? 中的英雄們,添加下面的代碼來(lái)獲取所選英雄的 ?id?。這個(gè)代碼片段假設(shè)你有一個(gè)英雄列表、一個(gè)英雄服務(wù)、一個(gè)能獲取你的英雄的函數(shù),以及用來(lái)渲染你的列表和細(xì)節(jié)的 HTML,就像在《英雄之旅》例子中一樣。

heroes$: Observable;
selectedId: number;
heroes = HEROES;

ngOnInit() {
  this.heroes$ = this.route.paramMap.pipe(
    switchMap(params => {
      this.selectedId = Number(params.get('id'));
      return this.service.getHeroes();
    })
  );
}

接下來(lái),在要導(dǎo)航到的組件中,導(dǎo)入以下成員。

import { Router, ActivatedRoute, ParamMap } from '@angular/router';
import { Observable } from 'rxjs';

在組件類的構(gòu)造函數(shù)中注入 ?ActivatedRoute ?和 ?Router?,這樣在這個(gè)組件中就可以用它們了:

hero$: Observable;

  constructor(
    private route: ActivatedRoute,
    private router: Router  ) {}

  ngOnInit() {
    const heroId = this.route.snapshot.paramMap.get('id');
    this.hero$ = this.service.getHero(heroId);
  }

  gotoItems(hero: Hero) {
    const heroId = hero ? hero.id : null;
    // Pass along the hero id if available
    // so that the HeroList component can select that item.
    this.router.navigate(['/heroes', { id: heroId }]);
  }

惰性加載

你可以配置路由定義來(lái)實(shí)現(xiàn)惰性加載模塊,這意味著 Angular 只會(huì)在需要時(shí)才加載這些模塊,而不是在應(yīng)用啟動(dòng)時(shí)就加載全部。 另外,你可以在后臺(tái)預(yù)加載一些應(yīng)用部件來(lái)改善用戶體驗(yàn)。

防止未經(jīng)授權(quán)的訪問(wèn)

使用路由守衛(wèi)來(lái)防止用戶未經(jīng)授權(quán)就導(dǎo)航到應(yīng)用的某些部分。Angular 中提供了以下路由守衛(wèi):

  • ?CanActivate ?
  • ?CanActivateChild ?
  • ?CanDeactivate ?
  • ?Resolve ?
  • ?CanLoad ?

要想使用路由守衛(wèi),可以考慮使用無(wú)組件路由,因?yàn)檫@對(duì)于保護(hù)子路由很方便。

為你的守衛(wèi)創(chuàng)建一項(xiàng)服務(wù):

ng generate guard your-guard

請(qǐng)?jiān)谑匦l(wèi)類里實(shí)現(xiàn)你要用到的守衛(wèi)。下面的例子使用 ?CanActivate ?來(lái)保護(hù)該路由。

export class YourGuard implements CanActivate {
  canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): boolean {
      // your  logic goes here
  }
}

在路由模塊中,在 ?routes ?配置中使用相應(yīng)的屬性。這里的 ?canActivate ?會(huì)告訴路由器它要協(xié)調(diào)到這個(gè)特定路由的導(dǎo)航。

{
  path: '/your-path',
  component: YourComponent,
  canActivate: [YourGuard],
}

鏈接參數(shù)數(shù)組

鏈接參數(shù)數(shù)組保存路由導(dǎo)航時(shí)所需的成分:

  • 指向目標(biāo)組件的那個(gè)路由的路徑(path)
  • 必備路由參數(shù)和可選路由參數(shù),它們將進(jìn)入該路由的 URL

可以把 ?RouterLink ?指令綁定到一個(gè)數(shù)組,就像這樣:

<a [routerLink]="['/heroes']">Heroes</a>

在指定路由參數(shù)時(shí),使用如下的兩元素?cái)?shù)組:

<a [routerLink]="['/hero', hero.id]">
  <span class="badge">{{ hero.id }}</span>{{ hero.name }}
</a>

可以在對(duì)象中提供可選的路由參數(shù),比如 ?{ foo: 'foo' }? :

<a [routerLink]="['/crisis-center', { foo: 'foo' }]">Crisis Center</a>

這三個(gè)例子涵蓋了你在單級(jí)路由的應(yīng)用中所需的一切。不過(guò),在你添加一個(gè)像危機(jī)中心一樣的子路由時(shí),你可以創(chuàng)建新鏈接數(shù)組。

下面這個(gè)最小化 ?RouterLink ?例子是基于危機(jī)中心指定的默認(rèn)子路由構(gòu)建的。

<a [routerLink]="['/crisis-center']">Crisis Center</a>

請(qǐng)注意以下事項(xiàng):

  • 數(shù)組中的第一個(gè)條目標(biāo)記出了父路由(?/crisis-center?)。
  • 這個(gè)父路由沒(méi)有參數(shù)。
  • 沒(méi)有默認(rèn)的子路由,因此你得選取一個(gè)。
  • 你決定跳轉(zhuǎn)到 ?CrisisListComponent?,它的路由路徑是'/',但你不用顯式的添加它。

考慮以下路由器鏈接,它將從應(yīng)用的根目錄導(dǎo)航到巨龍危機(jī)(Dragon Crisis):

<a [routerLink]="['/crisis-center', 1]">Dragon Crisis</a>
  • 數(shù)組中的第一個(gè)條目標(biāo)記出了父路由(?/crisis-center?)。
  • 這個(gè)父路由沒(méi)有參數(shù)。
  • 數(shù)組中的第二個(gè)條目('/:id')用來(lái)標(biāo)記出到指定危機(jī)的詳情頁(yè)的子路由。
  • 詳細(xì)的子路由需要一個(gè) ?id ?路由參數(shù)。
  • 你把巨龍危機(jī)的 ?id ?添加為該數(shù)組中的第二個(gè)條目(1)。
  • 最終生成的路徑是 ?/crisis-center/1?。

你也可以把危機(jī)中心的路由單獨(dú)重新定義為 ?AppComponent ?的模板:

template: `
  <h1 class="title">Angular Router</h1>
  <nav>
    <a [routerLink]="['/crisis-center']">Crisis Center</a>
    <a [routerLink]="['/crisis-center/1', { foo: 'foo' }]">Dragon Crisis</a>
    <a [routerLink]="['/crisis-center/2']">Shark Crisis</a>
  </nav>
  <router-outlet></router-outlet>
`

總之,你可以用一級(jí)、兩級(jí)或多級(jí)路由來(lái)寫應(yīng)用程序。 鏈接參數(shù)數(shù)組提供了用來(lái)表示任意深度路由的鏈接參數(shù)數(shù)組以及任意合法的路由參數(shù)序列、必須的路由器參數(shù)以及可選的路由參數(shù)對(duì)象。

LocationStrategy 和瀏覽器的網(wǎng)址樣式

當(dāng)路由器導(dǎo)航到一個(gè)新的組件視圖時(shí),它會(huì)用該視圖的 URL 來(lái)更新瀏覽器的當(dāng)前地址以及歷史。

現(xiàn)代 HTML 5 瀏覽器支持history.pushState API, 這是一項(xiàng)可以改變?yōu)g覽器的當(dāng)前地址和歷史,卻又不會(huì)觸發(fā)服務(wù)端頁(yè)面請(qǐng)求的技術(shù)。 路由器可以合成出一個(gè)“自然的”URL,它看起來(lái)和那些需要進(jìn)行頁(yè)面加載的 URL 沒(méi)什么區(qū)別。

下面是危機(jī)中心的 URL 在“HTML 5 pushState”風(fēng)格下的樣子:

localhost:3002/crisis-center/

老舊的瀏覽器在當(dāng)前地址的 URL 變化時(shí)總會(huì)往服務(wù)器發(fā)送頁(yè)面請(qǐng)求……唯一的例外規(guī)則是:當(dāng)這些變化位于“#”(被稱為“hash”)后面時(shí)不會(huì)發(fā)送。通過(guò)把應(yīng)用內(nèi)的路由 URL 拼接在 ?#? 之后,路由器可以獲得這條“例外規(guī)則”帶來(lái)的優(yōu)點(diǎn)。下面是到危機(jī)中心路由的“hash URL”:

localhost:3002/src/#/crisis-center/

路由器通過(guò)兩種 ?LocationStrategy ?提供者來(lái)支持所有這些風(fēng)格:

  1. ?PathLocationStrategy ?- 默認(rèn)的策略,支持“HTML 5 pushState”風(fēng)格。
  2. ?HashLocationStrategy ?- 支持“hash URL”風(fēng)格。

?RouterModule.forRoot()? 函數(shù)把 ?LocationStrategy ?設(shè)置成了 ?PathLocationStrategy?,使其成為了默認(rèn)策略。 你還可以在啟動(dòng)過(guò)程中改寫(override)它,來(lái)切換到 ?HashLocationStrategy ?風(fēng)格。

選擇路由策略

你必須在開(kāi)發(fā)項(xiàng)目的早期就選擇一種路由策略,因?yàn)橐坏┰搼?yīng)用進(jìn)入了生產(chǎn)階段,你網(wǎng)站的訪問(wèn)者就會(huì)使用并依賴應(yīng)用的這些 URL 引用。

幾乎所有的 Angular 項(xiàng)目都會(huì)使用默認(rèn)的 HTML 5 風(fēng)格。它生成的 URL 更易于被用戶理解,它也為將來(lái)做服務(wù)端渲染預(yù)留了空間。

在服務(wù)器端渲染指定的頁(yè)面,是一項(xiàng)可以在該應(yīng)用首次加載時(shí)大幅提升響應(yīng)速度的技術(shù)。那些原本需要十秒甚至更長(zhǎng)時(shí)間加載的應(yīng)用,可以預(yù)先在服務(wù)端渲染好,并在少于一秒的時(shí)間內(nèi)完整渲染在用戶的設(shè)備上。

只有當(dāng)應(yīng)用的 URL 看起來(lái)像是標(biāo)準(zhǔn)的 Web URL,中間沒(méi)有 hash(#)時(shí),這個(gè)選項(xiàng)才能生效。

<base href>

路由器使用瀏覽器的 history.pushState API 進(jìn)行導(dǎo)航。借助 ?pushState ?你自定義應(yīng)用中的 URL 路徑 ?localhost:4200/crisis-center?,應(yīng)用內(nèi)的 URL 和服務(wù)器的 URL 沒(méi)有區(qū)別。

現(xiàn)代的 HTML5 瀏覽器都支持 ?pushState?,這也就是為什么很多人把這種 URL 形式稱為 "HTML 5" 風(fēng)格的 URL。

你必須在應(yīng)用的 ?index.html? 中添加一個(gè) <base href> 元素才能讓 ?pushState ?路由正常工作。 瀏覽器要用 ?<base href>? 的值為引用 CSS、腳本和圖片文件時(shí)使用的相對(duì) URL 添加前綴。

請(qǐng)把 ?<base>? 元素添加在 ?<head>? 標(biāo)簽的緊后面。如果應(yīng)用的根目錄是 ?app ?目錄,那么就可以像這個(gè)應(yīng)用程序一樣,設(shè)置 ?index.html? 中的 ?href ?值。代碼如下。

<base href="/">

HTML5 網(wǎng)址和 <base href>

后面的指南中會(huì)引用 URL 的不同部分。下圖是這些部分所指內(nèi)容的梗概:

foo://example.com:8042/over/there?name=ferret#nose
\_/   \______________/\_________/ \_________/ \__/
 |           |            |            |        |
scheme    authority      path        query   fragment

由于路由器默認(rèn)使用 “HTML 5 pushState” 風(fēng)格,所以你必須用一個(gè) ?<base href>? 來(lái)配置該策略(Strategy)。

配置該策略的首選方式是往 ?index.html? 的 ?<head>? 中添加一個(gè)<base href> element標(biāo)簽。

<base href="/">

如果沒(méi)有該標(biāo)記,瀏覽器就可能無(wú)法在“深度鏈接”進(jìn)入應(yīng)用時(shí)加載資源(圖片,CSS,腳本)。

有些開(kāi)發(fā)人員可能無(wú)法添加 ?<base>? 元素,這可能是因?yàn)樗鼈儧](méi)有訪問(wèn) ?<head>? 或 ?index.html? 的權(quán)限。

它們?nèi)匀豢梢允褂?nbsp;HTML 5 格式的 URL,但要采取如下步驟進(jìn)行補(bǔ)救:

  1. 用適當(dāng)?shù)腫APP_BASE_HREF][]值提供(provide)路由器。
  2. 對(duì)所有 Web 資源(CSS、圖片、腳本和模板 HTML 文件)使用根 URL(高優(yōu)先度 URL)。
    • ?<base href>? 的 ?path ?應(yīng)該用 "/" 結(jié)尾,瀏覽器會(huì)忽略 ?path ?中最右邊的 "/" 后面的字符。
    • 如果 ?<base href>? 包含 ?query ?部分,則只有頁(yè)內(nèi)鏈接的 ?path ?部分為空并且沒(méi)有 ?query ?時(shí),才會(huì)使用這里的 ?query?。 這意味著 ?<base href>? 中的 ?query ?部分只有在使用 ?HashLocationStrategy ?策略時(shí)才有用。
    • 如果頁(yè)內(nèi)鏈接是根 URL(高優(yōu)先度 URL),則 ?<base href>? 不會(huì)使用。在這種方式下,?APP_BASE_HREF ?的優(yōu)先度將會(huì)導(dǎo)致所有由 Angular 創(chuàng)建的鏈接忽略 ?<base href>?。
    • ?<base href>? 中的片段(#后面的部分)永遠(yuǎn)不會(huì)被使用。

對(duì)所有 Web 資源使用絕對(duì)地址:CSS、圖片、腳本、模板 HTML。

HashLocationStrategy

可以在根模塊的 ?RouterModule.forRoot()? 的第二個(gè)參數(shù)中傳入一個(gè)帶有 ?useHash: true? 的對(duì)象,以回到基于 ?HashLocationStrategy ?的傳統(tǒng)方式。

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { Routes, RouterModule } from '@angular/router';

import { AppComponent } from './app.component';
import { PageNotFoundComponent } from './page-not-found/page-not-found.component';

const routes: Routes = [

];

@NgModule({
  imports: [
    BrowserModule,
    FormsModule,
    RouterModule.forRoot(routes, { useHash: true })  // .../#/crisis-center/
  ],
  declarations: [
    AppComponent,
    PageNotFoundComponent
  ],
  providers: [

  ],
  bootstrap: [ AppComponent ]
})
export class AppModule { }


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

掃描二維碼

下載編程獅App

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

編程獅公眾號(hào)