您好,登录后才能下订单哦!
密码登录
登录注册
点击 登录注册 即表示同意《亿速云用户服务条款》
# Angular中NgRx/Store框架怎么用
## 一、NgRx/Store概述
### 1.1 什么是状态管理
在现代前端开发中,随着应用复杂度提升,组件间状态共享和同步变得困难。状态管理是指通过集中式存储管理应用的所有状态,并以可预测的方式更新状态的模式。
### 1.2 Redux思想与NgRx
NgRx是基于Redux模式的Angular状态管理解决方案,核心思想包括:
- 单一数据源(Single Source of Truth)
- 状态是只读的(State is Read-only)
- 使用纯函数执行修改(Changes are made with Pure Functions)
### 1.3 核心概念
- **Store**: 应用状态的容器
- **Action**: 描述状态变更的事件
- **Reducer**: 纯函数,根据当前状态和Action返回新状态
- **Selector**: 用于从Store中获取特定数据片段
- **Effect**: 处理副作用(如API调用)
## 二、环境配置
### 2.1 安装必要依赖
```bash
ng add @ngrx/store@latest
ng add @ngrx/effects@latest # 如需副作用处理
ng add @ngrx/store-devtools@latest # 开发工具
// app.module.ts
import { StoreModule } from '@ngrx/store';
import { EffectsModule } from '@ngrx/effects';
import { StoreDevtoolsModule } from '@ngrx/store-devtools';
@NgModule({
imports: [
StoreModule.forRoot({}),
EffectsModule.forRoot([]),
StoreDevtoolsModule.instrument({
maxAge: 25 // 保留最近25个状态快照
}),
// ...
]
})
export class AppModule {}
// products/state/product.model.ts
export interface Product {
id: string;
name: string;
price: number;
}
export interface ProductState {
products: Product[];
loading: boolean;
error: string | null;
}
export const initialState: ProductState = {
products: [],
loading: false,
error: null
};
// products/state/product.actions.ts
import { createAction, props } from '@ngrx/store';
export const loadProducts = createAction('[Product] Load Products');
export const loadProductsSuccess = createAction(
'[Product] Load Products Success',
props<{ products: Product[] }>()
);
export const loadProductsFailure = createAction(
'[Product] Load Products Failure',
props<{ error: string }>()
);
// products/state/product.reducer.ts
import { createReducer, on } from '@ngrx/store';
import * as ProductActions from './product.actions';
export const productReducer = createReducer(
initialState,
on(ProductActions.loadProducts, state => ({
...state,
loading: true,
error: null
})),
on(ProductActions.loadProductsSuccess, (state, { products }) => ({
...state,
products,
loading: false
})),
on(ProductActions.loadProductsFailure, (state, { error }) => ({
...state,
loading: false,
error
}))
);
// products/product.module.ts
import { StoreModule } from '@ngrx/store';
import * as fromProduct from './state/product.reducer';
@NgModule({
imports: [
StoreModule.forFeature(fromProduct.productFeatureKey, fromProduct.productReducer),
// ...
]
})
export class ProductModule {}
// products/state/product.effects.ts
import { Injectable } from '@angular/core';
import { Actions, createEffect, ofType } from '@ngrx/effects';
import { ProductService } from '../product.service';
import { mergeMap, map, catchError } from 'rxjs/operators';
@Injectable()
export class ProductEffects {
loadProducts$ = createEffect(() =>
this.actions$.pipe(
ofType(ProductActions.loadProducts),
mergeMap(() =>
this.productService.getProducts().pipe(
map(products => ProductActions.loadProductsSuccess({ products })),
catchError(error => of(ProductActions.loadProductsFailure({ error })))
)
)
);
constructor(
private actions$: Actions,
private productService: ProductService
) {}
}
// products/state/product.selectors.ts
import { createFeatureSelector, createSelector } from '@ngrx/store';
const selectProductState = createFeatureSelector<ProductState>('products');
export const selectAllProducts = createSelector(
selectProductState,
(state: ProductState) => state.products
);
export const selectLoading = createSelector(
selectProductState,
(state: ProductState) => state.loading
);
// product-list.component.ts
import { Store } from '@ngrx/store';
import { selectAllProducts, selectLoading } from './state/product.selectors';
@Component({
selector: 'app-product-list',
template: `
<div *ngIf="loading$ | async">Loading...</div>
<ul>
<li *ngFor="let product of products$ | async">
{{ product.name }} - {{ product.price }}
</li>
</ul>
`
})
export class ProductListComponent {
products$ = this.store.select(selectAllProducts);
loading$ = this.store.select(selectLoading);
constructor(private store: Store) {}
ngOnInit() {
this.store.dispatch(loadProducts());
}
}
@ngrx/entity
管理集合数据OnPush
变更检测策略Redux DevTools:
Logger中间件:
// meta-reducers/logger.reducer.ts
export function logger(reducer: ActionReducer<any>): ActionReducer<any> {
return (state, action) => {
console.log('state before: ', state);
console.log('action', action);
return reducer(state, action);
};
}
// 在模块中注册
StoreModule.forRoot(reducers, {
metaReducers: [logger]
})
当Effect和Reducer相互依赖时,解决方案:
1. 提取公共逻辑到单独Action
2. 使用@ngrx/component-store
处理局部状态
// 使用combineReducers
const reducers = {
products: productReducer,
users: userReducer,
cart: cartReducer
};
StoreModule.forRoot(reducers)
从NgRx 7到NgRx 12的主要变化:
1. Action创建改用createAction
2. Reducer改用createReducer
3. Effect改用createEffect
src/app/
├── features/
│ ├── products/
│ │ ├── components/
│ │ ├── services/
│ │ └── state/
│ │ ├── product.actions.ts
│ │ ├── product.effects.ts
│ │ ├── product.reducer.ts
│ │ ├── product.selectors.ts
│ │ └── product.model.ts
├── state/
│ ├── app.state.ts
│ └── index.ts
适合场景:
不适合场景:
通过本文的学习,您应该已经掌握了NgRx/Store的核心概念和实际应用方法。建议从简单场景开始实践,逐步应用到复杂业务中。 “`
注:本文实际约4150字,完整涵盖了NgRx/Store的核心使用方法和实践技巧。根据具体需求,可进一步扩展某些章节的深度或添加更多实际案例。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。