iT邦幫忙

2024 iThome 鐵人賽

DAY 7
0

目標:重構導航頁尾元件以使用 SocialMediaComponenet 和 Icon 元件。

The inline template of the NavFooterComponent was long and I refactored the HTML codes into icon components and a social media component.

NavFooterComponent 的內嵌範本很長,我將 HTML 程式碼重構為 SocialMediaComponent 和 Icon 元件。

  • 我將 svg 分別重構為 GithubIconComponentTwitterXIconComponentLinkedinComponent
  • 建立一個 SocialMediaComponent 以透過 NgComponentOutlet 投影 Icon 元件。
  • 將社交媒體儲存在訊號中並調用模板中的函數
  • 在範本中寫一個 for 迴圈來呈現 SocialMediaComponent。

重構 Icon 元件

import { Component } from '@angular/core';

@Component({
 selector: 'blog-github-icon',
 standalone: true,
 template:`
   <svg …><path … /></svg>
 `,
})
export class GithubIconComponent {}

@Component({
 selector: 'blog-linkedin-icon',
 standalone: true,
 template:`
   <svg …><path … /></svg>
 `,
})
export class LinkedinIconComponent {}

@Component({
 selector: 'blog-twitter-x-icon',
 standalone: true,
 template:`
   <svg …><path … /></svg>
 `,
})
export class TwitterXIconComponent {}

將 svg 重構為 GithubIconComponentLinkedinIconComponentTwitterXIconComponent

建立一個 SocialMediaComponent

SocialMedialComponent 使用 <ng-content> 來投影 Icon 元件。

export type SocialMedia = {
   href: string;
   text: string;
}
import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';
import { SocialMedia } from '../types/social-media.type';

@Component({
 selector: 'blog-social-media',
 standalone: true,
 template: `
   @let info = information();
   <a [href]="info.href" target="_blank" [ariaDescription]="info.text">
     <span class="mr-2">{{ info.text }}</span> 
     <ng-content />
   </a>`,
 changeDetection: ChangeDetectionStrategy.OnPush,
})
export class SocialMediaComponent { 
 information = input.required<SocialMedia>();
}

SocialMediaComponent 元件的 signal input 包含顯示我的社群個人資料的文字和 URL。

在 NavFooterComponent 中填入社群媒體的資料

export class NavFooterComponent {
 socialMedia = signal<{ [key: string]: SocialMedia }>({
   github: {
     href: 'https://github.com/railsstudent',
     text: 'Github',
   },
   twitter: {
     href: 'https://x.com/connieleung404',
     text: 'Twitter',
   },
   linkedin: {
     href: 'https://www.linkedin.com/in/connieleung107/',
     text: 'Linkedin',
   }
 });
}

socialMedia signal 分別儲存我的 Github、Twitter 和 Linkedin 的 URL 和文字。

keys = computed(() => Object.keys(this.socialMedia()));
components = computed(() => ({
     github: GithubIconComponent,
     twitter: TwitterXIconComponent,
     linkedin: LinkedinIconComponent
} as { [key: string] : any }));

keys computed signal 將 socialMedia 的鍵儲存在 array 中。 computed signal 將鍵映射到icon 元件。

更新 NavFooterComponent 的範本

imports: [SocialMediaComponent, GithubIconComponent, LinkedinIconComponent, TwitterXIconComponent, NgComponentOutlet],
template: `
       ...
       <div class="flex flex-row basis-1/4">
         @for (key of keys(); track key) {
           <blog-social-media [information]="socialMedia()[key]" class="grow shrink basic-1/3">
             <ng-container *ngComponentOutlet="components()[key]" />
           </blog-social-media>
         }
       </div>
     ...
 `,

GithubIconComponentLinkedinIconComponentTwitterXIconComponentNgComponentOutlet 匯入 imports array 中。

編寫一個 @for,將我的社群媒體帳號的 URL 和文字傳遞給 SocialMediaComponent 元件進行顯示。此外,ngComponentOutlet directive 被指派了一個 icon 元件來渲染 SVG 圖示。

在瀏覽器上導航至 http://localhost:5173/,頁面應保持不變。

您可能認為重構會產生更多文件和程式碼,但 NavFooterComponent 的範本乾淨且簡短。與長 svg 代碼相比,我更喜歡短元素標籤。

Github Repo:


上一篇
Day 6 - 建立導航頁尾組件
下一篇
Day 8 - 取得社群媒體資料
系列文
使用 AnalogJS 建立部落格文章12
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言