目標:從 JSON 檔案中取得我的社群媒體資料
我希望保持 NavFooterComponent
元件較小,並將靜態社交媒體簡介封裝在 JSON 檔案中。
social-media.json
來儲存我的 GitHub、Twitter 和 Linkedin 的簡介{
"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"
}
}
新增 /assets/social-media.json
來儲存靜態資料。
SocialMediaService
有一個 getProfiles
方法來從 JSON 檔案擷取資料。
import { HttpClient } from '@angular/common/http';
import { inject, Injectable } from '@angular/core';
import { catchError, of, shareReplay } from 'rxjs';
import { SocialMedia } from '../types/social-media.type';
@Injectable({
providedIn: 'root'
})
export class SocialMediaService {
http = inject(HttpClient);
getProfiles() {
return this.http.get<{ [key: string]: SocialMedia }>('/assets/social-media.json')
.pipe(
catchError((err) => {
console.error(err);
return of({} as { [key: string]: SocialMedia } );
}),
shareReplay(1),
);
}
}
HttpClient
檢索 SocialMedia
物件。如果請求導致錯誤,catchError
運算子會捕獲錯誤並傳回一個空物件。 shareReplay
運算子會快取結果,因為資訊不會經常變更。
import { toSignal } from '@angular/core/rxjs-interop';
import { SocialMediaService } from '../services/social-media.service';
export class NavFooterComponent {
socialMediaService = inject(SocialMediaService);
socialMedia = toSignal(
this.socialMediaService.getProfiles(),
{ initialValue: {} as { [key: string]: SocialMedia } }
);
}
getProfiles
方法傳回一個 Observable
,我應用 toSignal
函數從中建立一個 signal
。keys
和 components
computed signals 沒有變化。
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>
...
`,
範本不會更改,因為它引用相同的 socialMedia
signal。
在瀏覽器上導航至 http://localhost:5173/,頁面應保持不變。
Github Repo: