0
0
Lập trình
Admin Team
Admin Teamtechmely

Tính Năng Cửa Hàng Tùy Chỉnh trong NgRx Signal Store

Đăng vào 2 ngày trước

• 5 phút đọc

Tính Năng Cửa Hàng Tùy Chỉnh trong NgRx Signal Store

Bạn có thể đã gặp phải tình huống này trước đây - bạn đang thêm một tính năng mới vào ứng dụng và nhận ra rằng bạn cần cùng một logic mà bạn đã viết ở nơi khác. Việc sao chép và dán có vẻ nhanh chóng, nhưng sớm muộn gì cũng dẫn đến mã trùng lặp và khó bảo trì. Trong quản lý trạng thái, cách để tránh vấn đề này là sử dụng các tính năng cửa hàng tùy chỉnh. Chúng cho phép bạn định nghĩa chức năng chung một lần và sau đó áp dụng một cách liền mạch cho nhiều cửa hàng.

Ví dụ Thực Tế

Để thấy cách hoạt động này trong thực tế, hãy tưởng tượng bạn đang xây dựng một ứng dụng Angular để theo dõi người chơi và đội trong một trò chơi cạnh tranh.

Bạn sẽ cần:

  • Cửa hàng người chơi – lưu trữ tên và vai trò của người chơi (mid, jungle, top, support, adc).
  • Cửa hàng đội – lưu trữ tên đội và số trận thắng.
  • Tính năng chia sẻ – cả người chơi và đội đều có một hạng (đồng, bạc, vàng…).

Thay vì sao chép logic xếp hạng trong cả hai cửa hàng, chúng ta có thể tách nó ra thành một tính năng tùy chỉnh và chỉ cần tái sử dụng.

Tạo Tính Năng Chia Sẻ

typescript Copy
// with-rank.feature.ts
import { signalStoreFeature, withState, withComputed } from '@ngrx/signals';
import { computed, Signal } from '@angular/core';

export type Rank = 'bronze' | 'silver' | 'gold';

export interface RankState {
  rank: Rank;
}

// tính năng tái sử dụng
export function withRank() {
  return signalStoreFeature(
    withState<RankState>({ rank: 'bronze' }),
    withComputed(({ rank }) => ({
      isGold: computed(() => rank() === 'gold'),
    }))
  );
}

// hàm trợ giúp để dễ dàng cập nhật trạng thái
export function setGold(): RankState {
  return { rank: 'gold' };
}

export function setSilver(): RankState {
  return { rank: 'silver' };
}

export function setBronze(): RankState {
  return { rank: 'bronze' };
}

Dưới đây là những gì chúng ta có:

  • trạng thái hạng
  • Các hàm trợ giúp như setGold, setSilversetBronze để cập nhật trạng thái.
  • Một thuộc tính tính toán isGold mà chúng ta có thể sử dụng trong các mẫu.

Cửa Hàng Người Chơi

typescript Copy
// player.store.ts
import { signalStore, withState, withMethods, patchState } from '@ngrx/signals';
import { withRank, setGold } from './with-rank.feature';

type Role = 'mid' | 'jungle' | 'top' | 'adc' | 'support';

export interface PlayerState {
  name: string;
  role: Role;
}

export const PlayerStore = signalStore(
  withState<PlayerState>({ name: 'Faker', role: 'mid' }),
  withRank(),
  withMethods((store) => ({
    promoteToGold() {
      patchState(store, setGold());
    }
  }))
);

Người chơi của chúng ta giờ đây có:

  • tên,
  • vai trò,
  • và nhờ vào withRank → cũng có một hạng.

Cửa Hàng Đội

typescript Copy
// team.store.ts
import { signalStore, withState, withMethods, patchState } from '@ngrx/signals';
import { withRank, setGold } from './with-rank.feature';

export interface TeamState {
  teamName: string;
  wins: number;
}

export const TeamStore = signalStore(
  withState<TeamState>({ teamName: 'T1', wins: 0 }),
  withRank(),
  withMethods((store) => ({
    promoteTeamToGold() {
      patchState(store, setGold());
    }
  }))
);

Đội có:

  • teamName,
  • số trận thắng,
  • và một lần nữa, một hạng.

Sử Dụng PlayerStore trong Một Component

typescript Copy
// player-card.component.ts
import { Component, inject } from '@angular/core';
import { PlayerStore } from './player.store';

@Component({
  selector: 'app-player-card',
  template: `
    <div class="card">
      <h2>{{ playerStore.name() }} — {{ playerStore.role() }}</h2>

      <p>Hạng: <strong>{{ playerStore.rank() }}</strong></p>

      @if (playerStore.isGold()) {
        <p>🏅 Người chơi này là Vàng!</p>
      }

      <button (click)="playerStore.promoteToGold()">Thăng chức lên Vàng</button>
    </div>
  `,
})
export class PlayerCardComponent {
  playerStore = inject(PlayerStore);
}

Sử Dụng TeamStore trong Một Component

typescript Copy
// team-card.component.ts
import { Component, inject } from '@angular/core';
import { TeamStore } from './team.store';

@Component({
  selector: 'app-team-card',
  template: `
    <div class="card">
      <h2>{{ teamStore.teamName() }}</h2>

      <p>Số trận thắng: {{ teamStore.wins() }}</p>
      <p>Hạng: <strong>{{ teamStore.rank() }}</strong></p>

      @if (teamStore.isGold()) {
        <p>🏆 Đội này là Vàng!</p>
      }

      <button (click)="teamStore.promoteTeamToGold()">Thăng chức đội lên Vàng</button>
    </div>
  `,
})
export class TeamCardComponent {
  teamStore = inject(TeamStore);
}

Tại đây, chúng ta tiêm PlayerStore hoặc TeamStore, hiển thị thông tin liên quan và cho phép thăng chức một lần nhấp lên hạng vàng (nếu chỉ có việc xếp hạng trong các trò chơi dễ dàng như vậy 😂).

Lợi Ích Đạt Được

Bằng cách tách hạng thành một tính năng tùy chỉnh, chúng ta đã tránh được việc lặp lại logic trong nhiều cửa hàng. Cả người chơi và đội đều chia sẻ cùng một tính năng, và chúng ta có thể mở rộng nó trong tương lai nếu cần.

Hãy nghĩ về các tính năng cửa hàng tùy chỉnh như các nâng cấp trong một trò chơi, bạn tạo chúng một lần và sau đó sử dụng chúng ở bất cứ đâu cần thiết cho một cú hích thêm.

Những Lợi Ích Chính:

  • ✅ Mã sạch hơn
  • ✅ Trạng thái & phương thức tái sử dụng
  • ✅ Giảm thiểu trùng lặp

Và phần tốt nhất: các cửa hàng của bạn vẫn gọn gàng và tập trung vào các trách nhiệm cụ thể của chúng.

Những Lưu Ý Quan Trọng

  • Nên sử dụng các tính năng cửa hàng tùy chỉnh để giảm thiểu mã lặp lại, đặc biệt trong các ứng dụng lớn.
  • Cần cẩn thận trong việc đặt tên cho các hàm và biến để đảm bảo tính rõ ràng và dễ hiểu cho người đọc.

Kết Luận

Việc sử dụng các tính năng cửa hàng tùy chỉnh trong NgRx Signal Store không chỉ giúp tổ chức mã của bạn tốt hơn mà còn tạo ra một trải nghiệm phát triển hiệu quả hơn. Hãy thử áp dụng phương pháp này trong các dự án của bạn và cảm nhận sự khác biệt!

Câu Hỏi Thường Gặp

  1. Tính năng cửa hàng tùy chỉnh là gì?
    Tính năng cửa hàng tùy chỉnh cho phép bạn định nghĩa chức năng chung một lần và tái sử dụng nó trong nhiều cửa hàng khác nhau.

  2. Lợi ích của việc sử dụng tính năng cửa hàng tùy chỉnh là gì?
    Giúp giảm thiểu mã lặp lại, tăng tính tái sử dụng và dễ bảo trì.

  3. Có thể mở rộng tính năng cửa hàng tùy chỉnh không?
    Có, bạn có thể mở rộng và thêm chức năng mới vào các tính năng cửa hàng tùy chỉnh khi cần thiết.

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào