برنامه نویسی

[Angular, NgRx] بهینه سازی عملکرد: جداسازی و مدیریت حالت کارآمد در برنامه ها

سلام برادران. در طول کار، زمانی که نیاز به جداسازی حالت در برنامه Angular خود داشتم، با مشکلی مواجه شدم. پس از مواجهه با این مشکل، زمانی را صرف تحقیق دقیق و یادگیری نحوه حل آن کردم. امروز، خوشحالم که دانش و تجربه خود را دوباره از طریق ایجاد این سند به اشتراک می گذارم.
در برنامه های کاربردی وب بزرگ، مدیریت موثر حالت برای بهبود عملکرد و تجربه کاربر بسیار مهم است. به خصوص زمانی که یک وب سایت دارای برگه های زیادی با محتوا و داده های مختلف باشد، جداسازی حالت برای هر تب می تواند عملکرد برنامه را به میزان قابل توجهی بهبود بخشد. با این حال، در برخی موارد، مدیریت عمومی دولت می تواند منجر به یک وب سایت کند و ناکارآمد شود.
این مقاله به شما نشان می دهد که چگونه از مدیریت دولتی عمومی به مدیریت ایالت جداگانه برای هر برگه، به روشی سازماندهی شده و مؤثرتر تغییر دهید. ما از یک مثال خاص از یک برنامه مدیریت کتاب با دو تب استفاده خواهیم کرد: “همه کتاب ها” و “مورد علاقه”. بدین ترتیب، دید واضح و دقیقی در مورد چگونگی بهبود عملکرد برنامه با بهینه سازی مدیریت حالت دریافت خواهید کرد.
قبل از شروع، مطمئن شوید که دانش اولیه Angular و ngRx را دارید تا بتوانید به وضوح محتوای مقاله را درک کنید. خود را با تمرکز و حوصله آماده کنید، زیرا ما عمیقاً به مفاهیم فنی و نحوه اجرای آنها خواهیم پرداخت.

وضعیت فعلی

برنامه مدیریت کتاب ما در حال حاضر وضعیت را از طریق یک ساختار مشترک به شکل AppState مدیریت می کند که شامل دو بخش اصلی است: allBooks و favoriteBooks. هر یک از این بخش‌ها حاوی فهرستی از کتاب‌ها هستند اما صفحه‌بندی را پشتیبانی نمی‌کنند. جستجوی داده ها از سرور نیز از طریق یک API واحد انجام می شود و همه داده ها را به یکباره برمی گرداند.

interface AppState {
  pageName: string;
  pageDescription: string; 
  booksPage: {
    allBooks: {
      list: Book[];
    };
    favoriteBooks: {
      list: Book[];
    };
  };
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

مشکل

  1. مدیریت دولتی بهینه نیست: State در حال حاضر از صفحه بندی پشتیبانی نمی کند، که منجر به بارگیری و نمایش مقادیر زیادی از داده ها به یکباره می شود و باعث تاخیر می شود و عملکرد را تحت تاثیر قرار می دهد.
  2. از یک API واحد استفاده کنید: استفاده از یک API یکسان برای پرس و جوی همه داده ها ناکارآمد است، به خصوص زمانی که برنامه نیاز به مقیاس و بهینه سازی دارد. ### درخواست جدید

برای بهبود عملکرد و تجربه کاربر، باید:

  • صفحه بندی را برای فهرست کتاب ها و کتاب های مورد علاقه اضافه کنید.
  • وضعیت را برای هر برگه allBooks و favoriteBooks جدا و مدیریت کنید.
  • از API های جداگانه برای هر برگه برای پرس و جوی داده ها استفاده کنید، که اجازه می دهد داده ها به صورت تکه ای بارگیری شوند.

به روز رسانی ساختار دولت

AppState را برای پشتیبانی از صفحه بندی هر برگه به ​​روز کنید:

interface AppState {
  pageName: string;
  pageDescription: string; 
  booksPage: {
    allBooks: {
      list: Book[];
      pagination: Pagination;
    };
    favoriteBooks: {
      list: Book[];
      pagination: Pagination;
    };
  };
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

بخش خدمات پس زمینه

سرویس Backend را به دو سرویس جداگانه برای AllBooks و FavoriteBooks تقسیم کنید تا API را برای دریافت داده‌های بخش و پشتیبانی از صفحه‌بندی فراخوانی کنید.

تعریف اقدامات جدید

اقدامات جدیدی برای به‌روزرسانی فهرست کتاب و اطلاعات صفحه‌بندی برای هر برگه، همراه با اقدامات مربوط به مدیریت خطا ایجاد کنید.

به روز رسانی کاهش دهنده ها

کاهنده های مربوطه را برای انجام اقدامات جدید بسازید و وضعیت را برای هر قسمت به طور مستقل به روز کنید.

به روز رسانی جلوه ها

از افکت‌ها برای مدیریت منطق ناهمزمان، فراخوانی سرویس Backend و ارسال اقدامات مربوطه بر اساس نتایج استفاده می‌شود و به مدیریت مؤثر داده‌ها کمک می‌کند.

انتخابگرها را به روز کنید

انتخابگرها به‌روزرسانی شده‌اند تا به راحتی فهرست‌های کتاب، اطلاعات صفحه‌بندی و خطاها را از حالت بازیابی کنند، عملکرد را بهبود بخشیده و مدیریت داده‌ها را در اجزای آن آسان‌تر می‌کنند.

به روز رسانی کلاس جزء، خدمات صفحه

تجزیه اجزا و خدمات صفحه به ما کمک می کند تا داده ها و منطق هر قسمت از برنامه را با وضوح بیشتری مدیریت کنیم. در عین حال، به افزایش مقیاس پذیری و قابلیت نگهداری برنامه نیز کمک می کند.

1. بخش خدمات Backend

اولین کاری که باید انجام دهید این است که سرویس باطن را با افزودن روش های جدید تقسیم کنید. هر روش مسئول فراخوانی APIهای مربوطه برای دریافت داده برای هر قسمت از برنامه خواهد بود. در عین حال، این روش‌ها از صفحه‌بندی داده‌ها نیز پشتیبانی می‌کنند و به ما کمک می‌کنند تا داده‌ها را انعطاف‌پذیرتر و مؤثرتر مدیریت کنیم.

قبل از:

یک سرویس BooksService تمام انواع درخواست‌های API مربوط به کتاب‌ها را بدون در نظر گرفتن فهرست کل کتاب‌ها و کتاب‌های مورد علاقه مدیریت می‌کند.

@Injectable({ providedIn: 'root' })
export class BooksService {
  constructor(private http: HttpClient) {}

  getBooks(): Observable<{ allBooks: Book[], favoriteBooks: Book[] }> {
    // Gọi một API duy nhất để lấy tất cả sách và sách yêu thích
    return this.http.get<{ allBooks: Book[], favoriteBooks: Book[] }>('api/books');
  }
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

بعد از:

BooksService را به دو سرویس جداگانه تقسیم کنید: AllBooksService و FavoriteBooksService، که هر کدام ارتباطات API را به طور جداگانه برای هر برگه کنترل می کنند و از صفحه بندی پشتیبانی می کنند.

@Injectable({ providedIn: 'root' })
export class BooksService {
  constructor(private http: HttpClient) {}

  // Phương thức ban đầu không thay đổi
  getBooks(): Observable<{ allBooks: Book[], favoriteBooks: Book[] }> {
    return this.http.get<{ allBooks: Book[], favoriteBooks: Book[] }>('api/books');
  }

  // Thêm phương thức mới để lấy tất cả sách với phân trang
  getAllBooks(pagination: Pagination): Observable<{ list: Book[], pagination: Pagination }> {
    const params = new HttpParams()
      .set('page', pagination.currentPage.toString())
      .set('limit', pagination.itemsPerPage.toString());

    return this.http.get<{ list: Book[], pagination: Pagination }>('api/books/all', { params });
  }

  // Thêm phương thức mới để lấy sách yêu thích với phân trang
  getFavoriteBooks(pagination: Pagination): Observable<{ list: Book[], pagination: Pagination }> {
    const params = new HttpParams()
      .set('page', pagination.currentPage.toString())
      .set('limit', pagination.itemsPerPage.toString());

    return this.http.get<{ list: Book[], pagination: Pagination }>('api/books/favorites', { params });
  }
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این به BooksService انعطاف بیشتری در رسیدگی به درخواست‌های ظاهری مختلف می‌دهد، از دریافت کل فهرست کتاب بدون صفحه‌بندی تا دریافت داده‌ها به بخش با صفحه‌بندی، همه در یک مکان.

2. به روز رسانی اقدامات

در مرحله بعد، اقدامات موجود را تنظیم و گسترش خواهیم داد تا منعکس کننده تقسیم خدمات پشتیبان به خدمات جداگانه برای AllBooks و FavoriteBooks باشد. این امر مستلزم ایجاد کنش‌های جدید برای بارگیری داده‌ها برای هر بخش از برنامه به طور مستقل، و همچنین افزودن اقدامات برای مدیریت به‌روزرسانی‌های صفحه‌بندی داده‌ها است. بدین ترتیب، می‌توانیم داده‌های هر بخش از برنامه را به صورت انعطاف‌پذیرتر و مؤثرتری مدیریت و تنظیم کنیم.

قبل از:

از یک سری اقدامات کلی مانند LoadBooks برای جستجوی همه کتاب‌ها بدون تمایز بین فهرست کل و فهرست دلخواه استفاده کنید.

export const loadBooks = createAction('[Books Page] Load Books');
export const loadBooksSuccess = createAction('[Books Page] Load Success', props<{ allBooks: Book[], favoriteBooks: Book[] }>());
export const loadBooksFailure = createAction('[Books Page] Load Failure', props<{ error: any }>());
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

بعد از:

برای هر برگه اقدامات جداگانه ای مانند LoadAllBooks، LoadFavoriteBooks به همراه اقدامات مربوط به موفقیت و شکست، پشتیبانی از صفحه بندی تعریف کنید.

// Tải dữ liệu mặc định khi vào trang
export const loadBooks = createAction('[Books Page] Load Books');
export const loadBooksSuccess = createAction('[Books Page] Load Success', props<{ allBooks: Book[], favoriteBooks: Book[] }>());
export const loadBooksFailure = createAction('[Books Page] Load Failure', props<{ error: any }>());

// Tải sách cho từng tab với phân trang
export const loadAllBooks = createAction('[All Books] Load', props<{ pagination: Pagination }>());
export const loadAllBooksSuccess = createAction('[All Books] Load Success', props<{ list: Book[], pagination: Pagination }>());
export const loadAllBooksFailure = createAction('[All Books] Load Failure', props<{ error: any }>());

export const loadFavoriteBooks = createAction('[Favorite Books] Load', props<{ pagination: Pagination }>());
export const loadFavoriteBooksSuccess = createAction('[Favorite Books] Load Success', props<{ list: Book[], pagination: Pagination }>());
export const loadFavoriteBooksFailure = createAction('[Favorite Books] Load Failure', props<{ error: any }>());

// Cập nhật phân trang mà không tải lại danh sách sách
export const updateAllBooksPagination = createAction('[All Books] Update Pagination', props<{ pagination: Pagination }>());
export const updateFavoriteBooksPagination = createAction('[Favorite Books] Update Pagination', props<{ pagination: Pagination }>());
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

با این سازمان:

  • هنگامی که کاربر برای اولین بار وارد صفحه می شود، می توانید loadBooks را برای بارگیری داده های پیش فرض برای هر دو برگه بدون صفحه بندی ارسال کنید.
  • هنگامی که کاربران بین برگه‌ها جابه‌جا می‌شوند و/یا با ویژگی‌های صفحه‌بندی تعامل دارند (مانند ورق زدن صفحات یا تغییر تعداد موارد در هر صفحه)، می‌توانید اقدامات جداگانه‌ای مانند loadAllBooks، loadFavoriteBooks، updateAllBooksPagination، یا updateFavoriteBooksPagination را بسته به موقعیت خاص ارسال کنید.

3. Reducers را به روز کنید

در به‌روزرسانی Reducers، ساختار کاهنده‌ها را طوری تنظیم می‌کنیم که تقسیم داده‌ها را به بخش‌های جداگانه در برنامه منعکس کند. این شامل افزودن یک رشته جدید در کاهنده موجود برای پردازش داده های هر قسمت است. ما هنگام دریافت داده‌ها از اقدامات جدید ایجاد شده در بخش قبلی، به‌روزرسانی وضعیت را انجام خواهیم داد.

قبل از:

یک کاهنده booksPageReducer تمام اقدامات مربوط به کتاب ها را انجام می دهد.

const initialState: BooksPageState = {
  pageName: string;
  pageDescription: string;
  allBooks: {
    list: []
  },
  favoriteBooks: {
    list: []
  }
};

const booksPageReducer = createReducer(
  initialState,
  on(loadBooksSuccess, (state, { allBooks, favoriteBooks }) => ({
    ...state,
    allBooks: { ...state.allBooks, list: allBooks },
    favoriteBooks: { ...state.favoriteBooks, list: favoriteBooks }
  })),
  on(loadBooksFailure, (state, { error }) => ({
    ...state,
    // Xử lý lỗi tại đây
  }))
);
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

بعد از:

برای پشتیبانی از بارگیری داده‌های پیش‌فرض در ورودی صفحه و به‌روزرسانی داده‌ها به طور جداگانه با صفحه‌بندی برای هر برگه، باید کاهنده را به‌روزرسانی کنیم تا اقدامات مربوطه را انجام دهد.

// Khởi tạo state ban đầu
const initialState: BooksPageState = {
  pageName: string;
  pageDescription: string;
  allBooks: {
    list: [],
    pagination: {
      currentPage: 0,
      totalPages: 0,
      totalItems: 0,
      itemsPerPage: 0,
    }
  },
  favoriteBooks: {
    list: [],
    pagination: {
      currentPage: 0,
      totalPages: 0,
      totalItems: 0,
      itemsPerPage: 0,
    }
  },
  loading: false,
  error: null,
};

// Reducer cập nhật
const booksPageReducer = createReducer(
  initialState,
  // Xử lý tải dữ liệu mặc định khi vào trang
  on(loadBooks, state => ({ ...state, loading: true })),
  on(loadBooksSuccess, (state, { allBooks, favoriteBooks }) => ({
    ...state,
    allBooks: { ...state.allBooks, list: allBooks },
    favoriteBooks: { ...state.favoriteBooks, list: favoriteBooks },
    loading: false
  })),
  on(loadBooksFailure, (state, { error }) => ({ ...state, error, loading: false })),

  // Xử lý tải sách cho tab AllBooks với phân trang
  on(loadAllBooks, state => ({ ...state, loading: true })),
  on(loadAllBooksSuccess, (state, { list, pagination }) => ({
    ...state,
    allBooks: { list, pagination },
    loading: false
  })),
  on(loadAllBooksFailure, (state, { error }) => ({ ...state, error, loading: false })),

  // Xử lý tải sách cho tab FavoriteBooks với phân trang
  on(loadFavoriteBooks, state => ({ ...state, loading: true })),
  on(loadFavoriteBooksSuccess, (state, { list, pagination }) => ({
    ...state,
    favoriteBooks: { list, pagination },
    loading: false
  })),
  on(loadFavoriteBooksFailure, (state, { error }) => ({ ...state, error, loading: false })),

  // Xử lý cập nhật phân trang cho tab AllBooks
  on(updateAllBooksPagination, (state, { pagination }) => ({
    ...state,
    allBooks: { ...state.allBooks, pagination }
  })),

  // Xử lý cập nhật phân trang cho tab FavoriteBooks
  on(updateFavoriteBooksPagination, (state, { pagination }) => ({
    ...state,
    favoriteBooks: { ...state.favoriteBooks, pagination }
  }))
);

// Đừng quên export reducer
export default booksPageReducer;
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در این ساختار:

  • کنش‌های loadBooks، loadBooksSuccess و loadBooksFailure به مدیریت بارگیری پیش‌فرض داده‌ها هنگام بازدید کاربر برای اولین بار از صفحه کمک می‌کنند.
  • اقداماتی مانند loadAllBooks، loadAllBooksSuccess، loadAllBooksFailure، loadFavoriteBooks، loadFavoriteBooksSuccess، و loadFavoriteBooksFailure به مدیریت بارگیری داده ها با صفحه بندی خاص تب کمک می کند.
  • کنش‌های updateAllBooksPagination و updateFavoriteBooksPagination به شما امکان می‌دهند که اطلاعات صفحه‌بندی برای هر برگه بدون بارگیری مجدد فهرست کتاب به‌روزرسانی شود.
  • ویژگی بارگیری در حالت برای ردیابی وضعیت بارگیری درخواست های API استفاده می شود و به برنامه اجازه می دهد وضعیت بارگیری مربوطه را نمایش دهد.

4. به روز رسانی جلوه ها

در مرحله بعد، افکت‌ها را طوری تنظیم می‌کنیم که اثرات اقدامات و تعاملات جدید با خدمات باطن را کنترل کنیم. این شامل ایجاد افکت‌های جدید برای مدیریت بارگذاری داده‌ها برای هر قسمت از برنامه به‌طور مستقل، به‌جای استفاده از یک افکت مشترک مانند قبل است. همچنین تأثیر نیاز به به‌روزرسانی داده‌های صفحه‌بندی برای هر بخش از برنامه را کنترل خواهیم کرد.

قبل از:

برخی از جلوه‌ها تماس‌های رایج API برای کتاب‌ها را بدون جدا کردن برگه‌ها کنترل می‌کنند.

@Injectable()
export class BooksEffects {
  loadBooks$ = createEffect(() => this.actions$.pipe(
    ofType(loadBooks),
    mergeMap(() => this.booksService.getBooks().pipe(
      map(({ allBooks, favoriteBooks }) => loadBooksSuccess({ allBooks, favoriteBooks })),
      catchError(error => of(loadBooksFailure({ error })))
    ))
  ));

  constructor(
    private actions$: Actions,
    private booksService: BooksService
  ) {}
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

بعد از:

برای به‌روزرسانی BooksEffects و پشتیبانی از بارگیری کتاب‌ها با صفحه‌بندی برگه، می‌توانید با استفاده از اقدامات و سرویس‌هایی که تعریف کردیم، جلوه‌های جدیدی اضافه کنید.

@Injectable()
export class BooksEffects {
  // Effect ban đầu để tải toàn bộ sách khi vào trang
  loadBooks$ = createEffect(() => this.actions$.pipe(
    ofType(loadBooks),
    mergeMap(() => this.booksService.getBooks().pipe(
      map(({ allBooks, favoriteBooks }) => loadBooksSuccess({ allBooks, favoriteBooks })),
      catchError(error => of(loadBooksFailure({ error })))
    ))
  ));

  // Thêm effect để tải sách 'All Books' với phân trang
  loadAllBooks$ = createEffect(() => this.actions$.pipe(
    ofType(loadAllBooks),
    mergeMap(({ pagination }) => this.booksService.getAllBooks(pagination).pipe(
      map(({ list, pagination }) => loadAllBooksSuccess({ list, pagination })),
      catchError(error => of(loadAllBooksFailure({ error })))
    ))
  ));

  // Thêm effect để tải sách 'Favorite Books' với phân trang
  loadFavoriteBooks$ = createEffect(() => this.actions$.pipe(
    ofType(loadFavoriteBooks),
    mergeMap(({ pagination }) => this.booksService.getFavoriteBooks(pagination).pipe(
      map(({ list, pagination }) => loadFavoriteBooksSuccess({ list, pagination })),
      catchError(error => of(loadFavoriteBooksFailure({ error })))
    ))
  ));

  constructor(
    private actions$: Actions,
    private booksService: BooksService
  ) {}
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در کد بالا:

  • loadBooks$ جلوه اولیه برای بارگیری همه کتابها در هنگام ورود کاربر به صفحه است، بدون تغییر نسبت به قبل.
  • loadAllBooks$ یک افکت جدید برای بارگیری داده ها برای برگه All Books با صفحه بندی است. این افکت به اکشن loadAllBooks گوش می دهد، متد getAllBooks() را از BooksService با اطلاعات صفحه بندی فراخوانی می کند و بسته به نتایج برگردانده شده از API اقدام loadAllBooksSuccess یا loadAllBooksFailure را ارسال می کند.
  • loadFavoriteBooks$ یک افکت جدید برای بارگذاری داده ها برای برگه کتاب های مورد علاقه با صفحه بندی است. به طور مشابه با loadAllBooks$ کار می کند اما مختص کتاب های مورد علاقه است.

5. انتخابگرها را به روز کنید

در قسمت Selectors Update، انتخابگرها را طوری تنظیم می کنیم که ساختار جدید حالت و تغییرات داده ها را منعکس کند. این شامل ایجاد انتخابگرهای جدید برای دسترسی به داده‌ها برای هر بخش از برنامه، مانند AllBooks و FavoriteBooks می‌شود، در حالی که پرس‌و‌جوهای صفحه‌بندی داده‌ها را به طور موثر مدیریت می‌کند.

قبل از:

از انتخابگرهای عمومی برای دریافت لیست کتاب ها از ایالت استفاده کنید.

export const selectBooksPageState = (state: AppState) => state.booksPage;
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

بعد از:

ابتدا، بیایید مطمئن شویم که یک انتخابگر اولیه برای بازیابی booksPage از AppState داریم
سپس انتخابگرهای جدیدی برای همه کتاب‌ها و کتاب‌های مورد علاقه، از جمله فهرست کتاب و اطلاعات صفحه‌بندی ایجاد کنید:

export const selectBooksPageState = (state: AppState) => state.booksPage;

// Selector cho danh sách sách 'All Books'
export const selectAllBooksList = createSelector(
  selectBooksPageState, 
  (booksPage) => booksPage.allBooks.list
);
export const selectAllBooksPagination = createSelector(
  selectBooksPageState, 
  (booksPage) => booksPage.allBooks.pagination
);

// Selector cho danh sách sách 'Favorite Books'
export const selectFavoriteBooksList = createSelector(
  selectBooksPageState, 
  (booksPage) => booksPage.favoriteBooks.list
);
export const selectFavoriteBooksPagination = createSelector(
  selectBooksPageState, 
  (booksPage) => booksPage.favoriteBooks.pagination
);
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در کد بالا:

  • selectAllBooksList و selectFavoriteBooksList انتخابگرهایی هستند که به بازیابی فهرستی از کتاب ها از وضعیت برای هر برگه کمک می کنند.
  • selectAllBooksPagination و selectFavoriteBooksPagination انتخابگرهایی هستند که به بازیابی اطلاعات صفحه بندی از وضعیت هر برگه کمک می کنند.
  • به لطف این انتخابگرها، اجزای شما می‌توانند به راحتی در داده‌های خاصی که از حالت نیاز دارند، بدون نگرانی در مورد مدیریت منطق پیچیده بازیابی مستقیماً در مؤلفه مشترک شوند. این به سازماندهی بهتر کد، نگهداری آسان تر و قابلیت استفاده مجدد بیشتر کمک می کند.

6. کامپوننت را به روز کنید

بعدی به روز رسانی Component است که در آن عناصر UI را برای منعکس کردن ساختار جدید داده ها و وضعیت تنظیم می کنیم. این شامل به‌روزرسانی مؤلفه‌ها برای نمایش داده‌ها از بخش‌های جداگانه برنامه، مانند AllBooks و FavoriteBooks است. در عین حال، ما همچنین باید منطق اجزا را تنظیم کنیم تا اطمینان حاصل کنیم که آنها داده ها را به درستی نشان می دهند و تغییرات حالت را منعکس می کنند.

قبل از:

در اصل، BookPageComponent ممکن است به گونه‌ای طراحی شده باشد که کل داده‌های کتاب را به‌طور هم‌زمان بدون صفحه‌بندی و بدون مدیریت داده‌های رایج صفحه مانند نام صفحه و توضیحات بارگیری کند.

@Component({
  // Metadata
})
export class BookPageComponent implements OnInit {
  books$: Observable; // Dữ liệu sách từ state

  constructor(private store: Store) {}

  ngOnInit(): void {
    // Dispatch action để tải toàn bộ sách khi vào trang
    this.store.dispatch(loadBooks());
    this.books$ = this.store.pipe(select(selectBooks));
  }
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

بعد از:

در این حالت، هنگام دسترسی به صفحه، برنامه بدون نیاز به منتظر ماندن برای صفحه بندی، داده های کلی صفحه مانند نام صفحه، توضیحات صفحه و همچنین لیست کتاب ها را برای هر برگه بارگذاری می کند. و سپس، هنگامی که کاربر با صفحه بندی تعامل می کند، شما فقط داده های کتاب فردی را برای هر برگه به ​​روز می کنید. در اینجا نحوه به روز رسانی BookPageComponent آورده شده است:

@Component({
  // Metadata
})
export class BookPageComponent implements OnInit {
  pageData$: Observable; // Observable cho dữ liệu chung của trang
  allBooks$: Observable; 
  favoriteBooks$: Observable; 

  constructor(private store: Store) {}

  ngOnInit(): void {
    // Tải dữ liệu chung cho trang bao gồm tải sách ban đầu cho mỗi tab mà không phân trang
    this.store.dispatch(loadPageData());

    // Lấy dữ liệu chung của trang và sách từ state
    this.pageData$ = this.store.pipe(select(selectPageData));
    this.allBooks$ = this.store.pipe(select(selectAllBooksList));
    this.favoriteBooks$ = this.store.pipe(select(selectFavoriteBooksList));
  }

  loadBooksForTab(tab: 'all' | 'favorite', pagination: Pagination): void {
    if (tab === 'all') {
      this.store.dispatch(loadAllBooks({ pagination }));
    } else if (tab === 'favorite') {
      this.store.dispatch(loadFavoriteBooks({ pagination }));
    }
  }

  // Xử lý khi người dùng tương tác với phân trang
  onPageChange(tab: 'all' | 'favorite', page: number): void {
    this.loadBooksForTab(tab, { currentPage: page, itemsPerPage: 10 });
  }
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

نکات کلیدی:

  1. داده های عمومی صفحه:pageData$ یک Observable است که برای نمایش داده های کلی صفحه مانند نام و توضیحات صفحه استفاده می شود. عمل loadPageData در ngOnInit برای بارگیری این داده ارسال می شود.
  2. دانلود کتاب برای اولین بارعملکرد :loadBooks در ngOnInit ارسال می‌شود تا اولین فهرست کتاب‌ها را برای هر دو برگه بارگیری کند، و اطمینان حاصل شود که داده‌ها به محض بارگیری صفحه در دسترس هستند.
  3. دست زدن به صفحه بندی: loadBooksForTab روشی است که هنگام تعامل کاربر با صفحه‌بندی، داده‌های کتاب را برای برگه مربوطه بارگیری می‌کند، با استفاده از اقدامات loadAllBooks و loadFavoriteBooks با اطلاعات صفحه‌بندی خاص.
  4. پاسخ UI: هنگامی که کاربر با عناصر صفحه‌بندی ارتباط برقرار می‌کند، متد onPageChange فراخوانی می‌شود و دوباره loadBooksForTab را با اطلاعات صفحه و برگه جدید فراخوانی می‌کند. بنابراین، شما یک سازمان انعطاف‌پذیر خواهید داشت که امکان بارگیری داده‌های کلی صفحه و داده‌های کتاب را به محض دسترسی به صفحه فراهم می‌کند و از به‌روزرسانی داده‌های کتاب هنگام تعامل با صفحه‌بندی بدون تأثیر بر داده‌های کلی صفحه پشتیبانی می‌کند.

بنابراین، ما سفری را برای به‌روزرسانی و بهینه‌سازی BookPageComponent در برنامه مدیریت کتاب خود طی کرده‌ایم، از یک ساختار اولیه ساده، بدون پشتیبانی از صفحه‌بندی یا داده‌های کلی صفحه، به یک ساختار انعطاف‌پذیرتر، پشتیبانی از صفحه‌بندی و مدیریت داده‌های عمومی.
خلاصه تغییر:

  • ساختار وضعیت و سرویس: ما ساختار حالت را برای پشتیبانی از صفحه بندی به روز کرده ایم و روش هایی را برای پشتیبانی از بارگیری داده ها با صفحه بندی به سرویس اضافه کرده ایم.
  • اقدامات و کاهش دهنده ها: اقدامات جدید و کاهش دهنده های به روز شده برای مدیریت بارگیری و به روز رسانی کتاب ها با صفحه بندی، و همچنین پشتیبانی از بارگیری داده های کلی صفحه اضافه شده است.
  • انتخابگرها: انتخابگرهای جدید را به‌روزرسانی و ایجاد کنید تا داده‌های کتاب و داده‌های کلی صفحه را به طور مؤثر از حالت بازیابی کنید.
  • مؤلفه: منطق مؤلفه را به‌روزرسانی می‌کند تا از بارگیری اولیه داده‌ها بدون صفحه‌بندی و بارگذاری برگه‌ای داده‌ها با صفحه‌بندی هنگام تعامل با UI پشتیبانی کند، در حالی که داده‌های کلی صفحه را نیز مدیریت می‌کند. به‌روزرسانی BookPageComponent نشان می‌دهد که از طریق بهبود منطق و ساختار برنامه، می‌توانیم به تعادلی بین عملکرد و تجربه کاربر دست یابیم. این نه تنها برنامه شما را قوی تر و پاسخگوتر می کند، بلکه پایه ای محکم برای رشد و گسترش آینده ایجاد می کند. در پایان از شما تشکر می کنم و امیدوارم که این مقاله دیدگاه روشن و گام های مشخصی را برای بهبود عملکرد و مدیریت وضعیت در پروژه به شما ارائه کرده باشد.

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا