Angular: 状态管理

为什么需要状态管理

我懒得翻译,直接截取Redux文档的图,附上。阅读时,请把Redux默认更改为Ngrx, 你会发现一样能行得通。(手动狗头)

何时使用

核心概念

a. Store:应用的单一状态树,用于存储全局状态。 b. Actions:描述意图的纯对象,触发状态的改变。 c. Reducers:响应 Action,并基于当前状态生成新的状态。 d. Selectors:从状态树中派生出所需要的数据(避免组件直接操作 Store)。 e. Effects:管理非同步逻辑(例如 API 请求)或副作用,解耦业务逻辑。

核心概念图

使用步骤

状态管理中, 不论前端哪一种框架, 如下三项都是必须的。即

  1. store: 存储整个应用状态树的对象。它是全局单例的,提供dispatch方法发送Action,以及select方法获取状态切片。

  2. actions: actions 是描述状态变化事件的类。它们有一个 type 字符串和一个可选的 payload 数据。Actions 是Store唯一的信息来源,通过dispatch方法发送到Store。

  3. reducers: Reducers 是纯函数,负责处理状态的变化。它们接收当前状态和一个Action,返回一个新的状态(不可变更新)。Reducers必须保持纯净,不产生副作用。

这三项使用的基本步骤如下所示

代码实例

第一步, 定义好自己的初始化State

第二步,定义Actions

第三步, 定义reducers

第四步, 注册reducers

store文件夹的整体目录

selector的使用

用于从 Store 中提取和组合状态的记忆函数

如何使用

本例中, 我需要实现的功能是,父组件可以实时获取各子组件中的值,并按Save按钮存储对应的值。如图所示:

效果展示

代码展示

父组件

HTML

HTML 复制代码
<nz-tabset>
  <nz-tab nzTitle="Tab 1">
    <app-child1></app-child1>
  </nz-tab>
  <nz-tab nzTitle="Tab 2">
    <app-child2></app-child2>
  </nz-tab>
  <nz-tab nzTitle="Tab 3">
    <app-child3></app-child3>
  </nz-tab>
  <nz-tab nzTitle="Tab 4">
    <app-child4></app-child4>
  </nz-tab>
  <nz-tab nzTitle="Tab 5">
    <app-child5></app-child5>
  </nz-tab>
</nz-tabset>

<nz-divider></nz-divider>
<pre>{{ childData | json }}</pre>


<button nz-button nzType="primary" (click)="storeData()">Save</button>
<ng-container *ngIf="showResult">
  <pre>{{ saveData | json }}</pre>
</ng-container>

TypeScript

typeScript 复制代码
import { Component, OnInit } from '@angular/core';
import {Store} from "@ngrx/store";
import {AppState} from "../../store";
import {selectAllChildValues} from "../../store/selectors/vendor-code.selectors";

@Component({
  selector: 'app-view-vendor-code',
  templateUrl: './view-vendor-code.component.html',
  styleUrls: ['./view-vendor-code.component.css']
})
export class ViewVendorCodeComponent implements OnInit {
  childData: object = {};
  saveData: object = {};
  showResult = false;

  testData: any;

  constructor(
    private store: Store<AppState>
  ) {
    this.testData = this.store.select(state => state.vendorCodeReducer).subscribe(res => {
      console.log(res);
    })
  }

  ngOnInit(): void {
    // 从 Store 获取所有子组件的值
    this.store.select(selectAllChildValues).subscribe((data) => {
      this.childData = data;
    });
  }


  storeData() {
    console.log('存储的内容为:', this.childData);
    // 执行存储逻辑,比如发请求到后端存储
    this.showResult = true;
    this.saveData = this.childData;
  }
}

子组件

HTML

HTML 复制代码
<div>
  <label>Enter data for {{ childKey }}:</label>
  <input
    type="text"
    [(ngModel)]="inputData"
    (input)="updateService()"
    placeholder="Enter data"
  />
</div>

TypeScript

TypeScript 复制代码
import { Component, OnInit } from '@angular/core';
import {Store} from "@ngrx/store";
import {updateChildValue} from "../../../store/actions/vendor-code.actions";
import {selectChildValue} from "../../../store/selectors/vendor-code.selectors";

@Component({
  selector: 'app-child1',
  templateUrl: './child1.component.html',
  styleUrls: ['./child1.component.css']
})
export class Child1Component implements OnInit {
  childKey = 'child1';
  inputData: string = ''; // 本地存储用户输入的数据

  constructor(private store: Store) { }

  ngOnInit(): void {
    // 获取某个子组件的状态
    this.store.select(selectChildValue('child1')).subscribe((childState) => {
      this.inputData  = childState.inputValue;
    });
  }

  updateService() {
    // 分发 Action 更新 Store
    this.store.dispatch(updateChildValue({ child:'child1', value:this.inputData }));
  }

}

selector的使用

不使用selector获取State的方式

官方文档

ngrx.io/

可参考文档

因 ngRx是纯英文文档, 故可参考Redux中文文档进行核心概念的理解 cn.redux.js.org/api/store

相关推荐
飞翔的佩奇15 分钟前
【完整源码+数据集+部署教程】【天线&水】舰船战舰检测与分类图像分割系统源码&数据集全套:改进yolo11-repvit
前端·python·yolo·计算机视觉·数据集·yolo11·舰船战舰检测与分类图像分割系统
哆啦A梦15881 小时前
点击Top切换数据
前端·javascript·vue.js
程序猿追2 小时前
Vue组件化开发
前端·html
艾德金的溪2 小时前
redis-7.4.6部署安装
前端·数据库·redis·缓存
小光学长2 小时前
基于Vue的2025年哈尔滨亚冬会志愿者管理系统5zqg6m36(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
前端·数据库·vue.js
@PHARAOH2 小时前
WHAT - 受控组件和非受控组件
前端·javascript·react.js
生莫甲鲁浪戴2 小时前
Android Studio新手开发第二十六天
android·前端·android studio
JH30733 小时前
B/S架构、HTTP协议与Web服务器详解
前端·http·架构
yi碗汤园3 小时前
【超详细】C#自定义工具类-StringHelper
开发语言·前端·unity·c#·游戏引擎
Kevin Wang7274 小时前
解除chrome中http无法录音问题,权限
前端·chrome