您的位置:首页 > 新闻 > 会展 > Angular之store全局状态管理 浅学

Angular之store全局状态管理 浅学

2024/10/12 2:24:24 来源:https://blog.csdn.net/qq_44327851/article/details/140524783  浏览:    关键词:Angular之store全局状态管理 浅学

        在 Angular 应用中,我们可以使用 @ngrx/store 进行状态管理可以有效地管理和跟踪应用程序的状态变化。@ngrx/store 是基于 Redux 模式的状态管理库,它提供了一种集中式存储管理应用程序状态的方式。以下是关于 @ngrx/store 的详细解释和使用方法:

前言

   @ngrx/store 提供了一种强大的机制来管理 Angular 应用程序的状态,使得应用程序的状态变化变得可预测和可追踪。通过定义 actions、reducers 和 selectors,并使用 select 函数来订阅状态变化,我们可以实现高效的状态管理,同时提高应用程序的可维护性和可测试性。同时,结合 Effects 可以处理复杂的异步逻辑,使得应用程序的状态管理更加完善和健壮。

1. 核心概念

1.1. Store

        Store是整个应用程序状态的单一来源。它是一个 RxJS Observable,用于订阅状态的变化。通过 Store,我们可以获取、更新和订阅应用程序中的状态。

1.2. State

        State 是应用程序的当前状态,通常表示为一个 JavaScript 对象。在 @ngrx/store  中,所有的状态都被组织成一个状态树,每个部分状态(或称为状态片段)都由一个 reducer 函数管理。

1.3. Actions

        Actions 是一个描述状态变化的简单对象,它包含了一个 type属性和可选的playload属性。通过 dispatching actions,我们可以触发状态的变化。

1.4. Reducers

       Reducers是纯函数,它接收当前状态和一个 action,并返回新的状态。Reducers 用于处理不同类型的 actions,更新相应的部分状态。

2. 安装和配置 @ngrx/store

2.1. 安装 @ngrx/store
npm install @ngrx/store --save
2.2. 在 Angular 应用中配置 StoreModule

        在 Angular 的根模块(通常是 AppModule)中导入 StoreModule.forRoot(),并传入一个包含所有 reducers 的对象。

// app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { StoreModule } from '@ngrx/store';
import { reducers, metaReducers } from './reducers'; // 导入应用程序的 reducers@NgModule({imports: [BrowserModule,StoreModule.forRoot(reducers, {metaReducers,runtimeChecks: {strictStateImmutability: true,strictActionImmutability: true,}})],declarations: [],bootstrap: []
})
export class AppModule { }
  • reducers是一个对象,包含了应用程序的所有 reducer 函数。
  • metaReducers是一些处理 reducer 的高阶函数,例如日志记录、状态恢复等。
  • runtimeChecks是一个可选配置对象,用于开启严格的状态和 action 不可变性检查。

3. 创建和使用 Actions、Reducers 和 State

3.1. 定义 Actions
// user.actions.ts
import { createAction, props } from '@ngrx/store';
import { User } from './user.model';export const setUser = createAction('[User] Set User', props<{ user: User }>());export const clearUser = createAction('[User] Clear User');
3.2. 创建 Reducers
// user.reducer.ts
import { Action, createReducer, on } from '@ngrx/store';
import { User } from './user.model';
import * as UserActions from './user.actions';export interface UserState {user: User | null;
}export const initialState: UserState = {user: null,
};const userReducer = createReducer(initialState,on(UserActions.setUser, (state, { user }) => ({ ...state, user })),on(UserActions.clearUser, (state) => ({ ...state, user: null })),
);export function reducer(state: UserState | undefined, action: Action) {return userReducer(state, action);
}
3.3. 使用 State 和 Dispatch Actions
// user.component.ts
import { Component } from '@angular/core';
import { Store } from '@ngrx/store';
import { AppState } from './app.state'; // 应用状态的类型定义
import { setUser, clearUser } from './store/user/user.actions'; // Actions 的导入@Component({selector: 'app-user',templateUrl: './user.component.html',styleUrls: ['./user.component.css']
})
export class UserComponent {constructor(private store: Store<AppState>) { }setUser(): void {const user = { id: '1', name: 'John Doe', email: 'john.doe@example.com' };this.store.dispatch(setUser({ user }));}clearUser(): void {this.store.dispatch(clearUser());}}

4. 在组件中使用 select 函数获取状态

4.1. 定义选择器函数
// user.selector.ts
import { createSelector, createFeatureSelector } from '@ngrx/store';
import { AppState } from '../../app.state'; // 应用状态的类型定义
import { UserState } from './user.reducer'; // 用户状态的类型定义// 创建特性选择器,用于选择用户状态
export const selectUserState = createFeatureSelector<AppState, UserState>('user');// 创建选择器函数,用于选择用户信息
export const getUser = createSelector(selectUserState,(state: UserState) => state.user
);
4.2. 在组件中使用 select 函数订阅状态
// user.component.ts
import { Component, OnInit } from '@angular/core';
import { Store, select } from '@ngrx/store';
import { AppState } from './app.state'; // 应用状态的类型定义
import { Observable } from 'rxjs';
import { getUser } from './store/user/user.selector'; // 选择器函数的导入
import { User } from './store/user/user.model'; // 用户模型的导入@Component({selector: 'app-user',templateUrl: './user.component.html',styleUrls: ['./user.component.css']
})
export class UserComponent implements OnInit {user$: Observable<User>; // 声明一个可观察对象,用来订阅用户状态constructor(private store: Store<AppState>) { }ngOnInit(): void {this.user$ = this.store.pipe(select(getUser)); // 使用 select 函数选择用户状态}
}
4.3. 在模板中使用 Async 管道订阅状态
<!-- user.component.html -->
<div *ngIf="user$ | async as user"><p>User Name: {{ user.name }}</p><p>User Email: {{ user.email }}</p>
</div>

5. 异步状态管理

        对于异步操作(如 HTTP 请求),可以使用 Effects,它允许我们在响应 action 时执行副作用,并将结果作为新的 action 分发到 store 中。这样可以保持 reducer 函数的纯粹性。

6. forFeature方法

        在 @ngrx/store 中,forFeature 方法是用来在特性模块中注册和配置状态的一种重要方式。特性模块可以理解为应用程序中的一个子模块,它可能包含了相关的业务逻辑、状态管理和视图组件。使用 forFeature 可以使得特性模块中的状态管理更加模块化和独立,同时能够与全局状态进行合理的整合。

使用场景和示例
1. 在特性模块中注册状态

        假设我们有一个应用程序,其中有一个特性模块管理用户信息的状态。我们可以使用 forFeature 来注册并配置该特性模块的状态。

// user.reducer.ts
import { Action, createReducer, on } from '@ngrx/store';
import { User } from './user.model';
import * as UserActions from './user.actions';export interface UserState {user: User | null;
}export const initialState: UserState = {user: null,
};const userReducer = createReducer(initialState,on(UserActions.setUser, (state, { user }) => ({ ...state, user })),on(UserActions.clearUser, (state) => ({ ...state, user: null })),
);export function reducer(state: UserState | undefined, action: Action) {return userReducer(state, action);
}
2. 在特性模块中使用 forFeature

        在特性模块中,我们需要导入 StoreModule 和相应的 reducer 函数,并使用 forFeature 来注册该特性模块的状态。

// user.module.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { StoreModule } from '@ngrx/store';
import { reducer } from './user.reducer'; // 导入用户特性模块的 reducer@NgModule({declarations: [],imports: [CommonModule,StoreModule.forFeature('user', reducer), // 使用 forFeature 注册用户特性模块的状态],
})
export class UserModule { }
详细解释
  1. Reducer 定义

    user.reducer.ts 中定义了一个用户特性模块的 reducer 函数,它负责管理用户信息的状态变化。这里的 initialState 定义了初始的状态对象,userReducer 使用 createReducer 函数来处理不同类型的 action,并更新相应的状态。

  2. 特性模块中的 StoreModule.forFeature

    UserModule 中,我们使用 StoreModule.forFeature 方法来注册用户特性模块的状态。forFeature 方法接收两个参数:

    • 第一个参数是一个字符串,用来标识注册的状态在全局状态树中的位置。在这里我们使用 user,表示用户特性模块的状态将会存储在全局状态树的 user 键下。
    • 第二个参数是特性模块的 reducer 函数,用来管理特性模块中的状态变化。
  3. 在应用中使用特性模块

    在主模块或其他需要使用用户特性模块的地方,只需导入 UserModule,Angular 就会自动注册和配置该模块的状态。

// app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { StoreModule } from '@ngrx/store';
import { reducers, metaReducers } from './reducers'; // 导入应用程序的 reducers
import { UserModule } from './user/user.module'; // 导入用户特性模块@NgModule({imports: [BrowserModule,StoreModule.forRoot(reducers, { metaReducers }),UserModule, // 导入并使用用户特性模块],declarations: [],bootstrap: []
})
export class AppModule { }
优势和适用场景
  • 模块化:使用 forFeature 可以使得状态管理更加模块化,每个特性模块可以独立管理自己的状态和逻辑,提高了代码的可维护性和可重用性。
  • 分割状态:通过注册不同的特性模块,可以将全局状态树分割为多个小块,使得状态管理更加清晰和灵活。
  • 依赖注入:Angular 的依赖注入机制能够有效地管理特性模块的依赖关系,使得状态的使用和管理更加一致和可控。

参考博文

https://blog.51cto.com/devpoint/4925185

Angular Ngrx 里 Store 和 State 的关系-阿里云开发者社区

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com