選單
GSS 技術部落格
在這個園地裡我們將從技術、專案管理、客戶對談面和大家分享我們多年的經驗,希望大家不管是喜歡或是有意見,都可以回饋給我們,讓我們有機會和大家對話並一起成長!
若有任何問題請來信:gss_crm@gss.com.tw
5 分鐘閱讀時間 (993 個字)

Angular #30 - 深入 Routing [3]

shutterstock_198004562
  • Child Routes

    • 一個 path 對上一個 component 感覺上限制很大(e.g. 很快所有會用的單子的用光了還列不完功能,或是明明四周圍都長得差不多,只是不同的內容,切到不同的 path)

      • 是否有注意到範例中最上方的導覽標題列一直都在,不論內容如何透過 routing 切換 component? 這是因為 Navbar 並不在 <routing-outlet> 的範圍內
      • 在 Routing 也可以有一樣的機制,在已經 route 到某個 path 的情況下,某部份保持原封不動,只讓特定區塊以 child route 的方式呈現
    • 前一篇提到 ForumsComponent 與 ForumComponent(單/複數)

      • 就目前的情境,前者主要列出所有的論壇,而後者列出個別論壇下的所有文章串

      • 承上,我們需要一個 ThreadComponent,而且它四周仍然被 ForumComponent 包圍著

      • 換句話說,path 的變化會如下:

        • /forums -> 最上層的 route
        • /forums/:forum_alias -> child route 顯示論壇
        • /forums/:forum_alias/:thread_alias -> 一樣是 child route,但某部份的 forum 持續顯示的情況下,進一步顯示文章串的內容
      • 到這裡可能有點暈,不如看個實例好了,調整 一下 forum.component.html:

          <header class="header">
              <div class="branding">
              <span class="title">{{forum?.title}}</span>
              </div>
          </header>
          <router-outlet></router-outlet>
        • 在最後面加上了 <router-outlet></router-outlet>
        • 承上,這樣可以保留 header 的區塊, 並讓文章串(ThreadComponent) 可以在 router-outlet 長出來
        • 假如 header 區塊有別的需求,像是要多一個按鈕可以新增文章串,那就只要動那個部份就可以了
      • 等等,我們似乎還少了一個動作,就是讓 Angular 知道這些規則,所以要調整 forums.module.ts 如下

          const forumRoutes: Routes = [
            { path: 'forums', component: ForumsComponent },
            {
              path: 'forums/:forum_alias',
              component: ForumComponent ,
              children: [
                { path: '', component: ThreadsComponent },
                { path: ':thread_alias', component: ThreadComponent }
              ]
            }
          ]
        • 重溫一下,第一個物件的規則是與到 forums 就載入 ForumsComponent,這個應該沒什麼問題
        • 再來這個物件變得好大,不但它的 path 本身變成 forums/:forum_alias,代表如果是 forums/xxx,就會載 ForumComponent
        • 還沒完呢,載入 ForumComponent 情況下,如果遇到 path 是空字串,就載入 ThreadsComponent,如果有 thread_alias,就載入 ThreadComponent
        • Forum 系列與 Thread 系列的 component 是分別載在不同的 router-outlet 的,因此就能讓異動的部份抽像化
      • 還…還有一件事呢,ThreadsComponent,要知道 URL 的變化才能導到文章串中的特定文章啊!

          import { Component, OnInit } from '@angular/core';
          import { ActivatedRoute, Params } from '@angular/router';
          import { ForumsService } from '../services/forums.service';
          import { Thread } from '../services/data';
        
          @Component({
            selector: 'app-threads',
            templateUrl: './threads.component.html',
            styleUrls: ['./threads.component.css']
          })
          export class ThreadsComponent implements OnInit {
            threads: Thread[];
        
            constructor(
              private route: ActivatedRoute,
              private forumService: ForumsService
            ) { }
        
            ngOnInit() {
              this.route.params.subscribe((params: Params) => {
                this.threads = this.forumService.forum(params['forum_alias']).threads;
              });
            }
          }
        • 跟前面的 ForumComponent 一樣,透過 ActivatedRoute subscribe 取得路徑參數,再透過 forumService 取得並設定 threads 的屬性值
      • 再來就是調整 threads.component.html

          <div class="content-container">
            <div class="content-area">
              <table class="table" *ngIf="threads">
                <tr>
                  <th>Thread</th>
                  <th>User</th>
                  <th>Last Post</th>
                  <th>Posts</th>
                </tr>
                <tr *ngFor="let thread of threads" [routerLink]="[thread.alias]">
                  <td>{{thread.title}}</td>
                  <td>{{thread.posts[0].username}}</td>
                  <td>{{thread.posts[0].timestamp | date:'medium'}}</td>
                  <td>{{thread.posts.length}}</td>
                </tr>
              </table>
            </div>
          </div>
        • 重點在有 NgFor 的那一列 tr,透過 [routerLink] 切換到某一個 thread
        • 因為是綁定相對路徑到 routerLink, 所以會接著 parent route 長 URL(e.g. /forum/:forum_alias/:thread_alias)
    • 現在我們可以選擇 Forum,並從中挑選 Thread,再來就是顯示 Thread 的內容了

      • 先實作 thread.component.ts

          import { Component, OnInit } from '@angular/core';
          import { ActivatedRoute, Params } from '@angular/router';
          import { ForumsService } from '../services/forums.service';
          import { Forum, Thread } from '../services/data';
        
          @Component({
            selector: 'app-thread',
            templateUrl: './thread.component.html',
            styleUrls: ['./thread.component.css']
          })
          export class ThreadComponent implements OnInit {
            forum: Forum;
            thread: Thread;
        
            constructor(
              private forumsService: ForumsService,
              private route: ActivatedRoute) { }
        
            ngOnInit() {
              this.route.params.subscribe((params:Params) => {
                let forum = this.route.snapshot.parent.params['forum_alias'];
                this.thread = this.forumsService.thread(forum, params['thread_alias']);
              })
            }
          }
        • 這邊有一個很重要的重點,就是透過 ActivatedRoutesnapshot 取得 parentRoute
        • 你也許會很納悶,不是有兩個 children,怎麼只針對有參數的處理? 這是因為另一個 children 的 path 是 '',所以它與 parent route 共享 pathparams
  • 小結:

    • 這幾篇 routing 開發是非常常用到的!
      • 前一篇提到 route 參數
      • 這一篇提到 child route,並可以取得 parent route 的參數
      • 下一篇會再提到一種…叫 secondary route 的,不用擔心,不會分不清楚的,它們差異很明顯
Angular #31 - 深入 Routing [4]
Angular # 29 - 深入 Routing [2]

相關文章

 

評論

尚無評論
已經注冊了? 這裡登入
Guest
2025/06/12, 週四

Captcha 圖像