iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 22
4
Modern Web

Angular 深入淺出三十天系列 第 22

[Angular 深入淺出三十天] Day 21 - 路由(四)

到目前為止,我們都是只有用 Component 來設定我們的路由。但在實際應用上,通常我們會將相關的功能包裝成一個一個的 NgModule ,而每個 NgModule,也其實都可以有自己的 RoutingModule。

舉例來說,我們先產生一個含有路由的 NgModule:

ng generate module feature --routing

並產生相對應的 Component:

ng generate component feature

接著設定路由:

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

import { FeatureComponent } from './feature.component';

const routes: Routes = [
  {
    path: 'feature',
    component: FeatureComponent
  }
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class FeatureRoutingModule { }

有發現這邊跟 AppRoutingModule 有個地方不太一樣嗎?

在 AppRoutingModule 的裝飾器裡, RouterModule 是使用 forRoot 的函式:

@NgModule({
  imports: [RouterModule.forRoot(routes, {
    useHash: true
  })],
  exports: [RouterModule]
})
export class AppRoutingModule { }

但在 FeatuerRouting 裡, RouterModule 卻是使用 forChild 的函式。

這是一個滿重要的區別,整個系統只有 AppRoutingModule 才會使用 forRoot ,其他的子路由模組都是使用 forChild

不過如果都是用 Angular CLI 來產生元件的話,倒是不用擔心這個。

接著我們先將 FeatureModule 引入到 AppModule 裡,並將其放在 AppRoutingModule 的上面,像是這樣:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

// Routing Module
import { AppRoutingModule } from './app-routing.module';

// Module
import { FeatureModule } from './feature/feature.module';

// Component
import { AppComponent } from './app.component';
import { HomeComponent } from './home/home.component';
import { AboutComponent } from './about/about.component';
import { LoginComponent } from './login/login.component';
import { LayoutComponent } from './layout/layout.component';

@NgModule({
  declarations: [
    AppComponent,
    HomeComponent,
    AboutComponent,
    LoginComponent,
    LayoutComponent
  ],
  imports: [
    BrowserModule,
    FeatureModule, // 放在這裡
    AppRoutingModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

接著再到瀏覽器上輸入 http://localhost:4200/#/feature 看看,應該就能夠看到 feature works! 的字樣:

Imgur

不過這邊要特別留意的是,我們含有路由設定的子功能模組一定要放在 AppRoutingModule 的上面

為什麼呢?

還記得我在路由(二)的時候有提到過路由在查找的時候是有順序性的嗎?

AppRoutingModule 裡有個萬用路由,如果我們把其他含有路由模組的功能模組擺在它之後的話,那我們永遠都別想進到放在它之後的子功能模組裡了。

不信?那我們來試試看:

imports: [
  BrowserModule,
  AppRoutingModule,
  FeatureModule
]

來看看位置對調之後的結果:

Imgur

你看,怎麼樣都進不去吧。

那為什麼會這樣咧?從資料面來看就知道了。

首先我們先打開 home.component.ts 檔,然後注入一個名為 Router 的 Service:

export class HomeComponent implements OnInit {

  constructor(private router: Router) { }

  ngOnInit() {
  }

}

這個名為 Router Service 是 Angular 的路由機制所提供的,之後會再跟大家介紹它。現在只是需要透過它取得我們目前所設定的路由,看看實際上的資料大概會長怎樣。

然後我們在 ngOnInit 的函式裡加入以下的程式碼:

console.log(this.router.config);

如此便能在控制台裡看到我們印出來的資料:

Imgur

你看!是不是跟我說的一樣?! 含有 feature 路由設定的 FeatureModule 因為在 AppRoutingModule 才引入的關係,導致其路由被放到萬用路由後面。

我們把 FeatureModule 跟 AppRoutingModule 的位置交換回來之後再看一次:

Imgur

交換回來之後就不會被放在萬用路由底下了,這就是為什麼萬用路由要放在 routes 陣列裡最後一個,以及 AppRoutingModule 為什麼要放在 imports 陣列裡最後一個的原因。

有了這樣的概念之後,未來才不會有怎麼設路由卻發現怎麼樣都進不去的問題。

那今天就先到這裡,接下來要介紹的是在實務上更為實用的功能噢!

敬請期待!!


上一篇
[Angular 深入淺出三十天] Day 20 - 路由(三)
下一篇
[Angular 深入淺出三十天] Day 22 - 路由(五)
系列文
Angular 深入淺出三十天33
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 則留言

0
thuartlynn
iT邦新手 5 級 ‧ 2021-11-17 17:32:02

Hi 作者大人,

請問我照著您說的要注意在app.module.ts中引入FeatureModule的位置,為何我的localhost:4200/#/feature還是redirect回login那頁?

我還嘗試把之前萬用的route砍掉,但一樣還是redirect回login....
https://ithelp.ithome.com.tw/upload/images/20211117/20123332pGn1Q6Fnkl.png
請問我有不小心遺漏了什麼重要的觀念嗎?

看更多先前的回應...收起先前的回應...
Leo iT邦新手 3 級 ‧ 2021-11-17 17:37:43 檢舉

Hi thuartlynn,

你可能要在 RouterModule 裡加上 enableTracing: true 的參數讓系統把 log 印出來才會知道。

我先猜是不是你沒有 enableHash: true 所導致的?

如果你沒有 enableHash: true 的話, localhost:4200/#/feature => 這個 URL 就不用 # ,只要 localhost:4200/feature 就好。

如果不是這個問題的話,可能要看一下你 AppRoutingModule 裡的設定才知道囉

https://ithelp.ithome.com.tw/upload/images/20211118/201233322akEyU68di.png
Hi 作者大人,
我今早重開資料夾,重新ng serve後,一切就正常了...您說的那些我都有保留著,新增那個feature的module後就沒動過,剛log出來也是正確的urlAfterRedirects: '/feature',昨天這邊怎樣都是'/login',所以....昨天真的不知道是哪兒出問題了...
真的超級感謝你,還是很快速的回答了我...

Leo iT邦新手 3 級 ‧ 2021-11-24 17:25:31 檢舉

Hi thuartlynn,

別客氣,人剛好在而已,大部分時間都是不在的XDDD

Hi 作者大人,

XD ,好在你就這麼剛好在,謝謝你之前寫的這一系列,讓我快速了解了Angular~感謝你

Leo iT邦新手 3 級 ‧ 2021-12-09 16:37:30 檢舉

Hi thuartlynn,

這是我的榮幸,也非常開心我的文章有幫到你^^

給你一個大大的讚~

0
memo
iT邦新手 5 級 ‧ 2022-03-15 18:24:01

您好,
想詢問一下,在routing.module 設定的 「useHash: true」
可不可以不要加這個呢?, 因為網站一般好像不太會看到「#」
例如:https://example.com/#/about (useHash)
https://example.com/about (可以是這個嗎)


自己這邊遇到的狀況是,
不用 useHash 的話,打包上架的網站
如果是使用點擊的方式,可以順利導向頁面;
但是自己手動改網址,就會變成 404 了 (╯︿╰)||

Leo iT邦新手 3 級 ‧ 2022-03-22 03:30:43 檢舉

Hi memo, 當然是看你的需求囉!

這其實是有歷史背景的XDDD

我要留言

立即登入留言