目標:重構導航頁尾元件以使用 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 元件。
GithubIconComponent
、TwitterXIconComponent
和 LinkedinComponent
。SocialMediaComponent
以透過 NgComponentOutlet
投影 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 重構為 GithubIconComponent
、 LinkedinIconComponent
和 TwitterXIconComponent
。
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。
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 元件。
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>
...
`,
將 GithubIconComponent
、LinkedinIconComponent
、TwitterXIconComponent
和 NgComponentOutlet
匯入 imports
array 中。
編寫一個 @for
,將我的社群媒體帳號的 URL 和文字傳遞給 SocialMediaComponent
元件進行顯示。此外,ngComponentOutlet
directive 被指派了一個 icon 元件來渲染 SVG 圖示。
在瀏覽器上導航至 http://localhost:5173/,頁面應保持不變。
您可能認為重構會產生更多文件和程式碼,但 NavFooterComponent
的範本乾淨且簡短。與長 svg 代碼相比,我更喜歡短元素標籤。
Github Repo: