angular状态管理方案(ngrx)

完全基于redux的ngrx方案,我们看看在angular中如何实现。通过一个简单的计数器例子梳理下整个流程

一 安装 :npm i ngrx/store

这里特别要注意一点:安装 @ngrx/store的时候会出现和angular版本不一致的问题

所以检查一下@angular/core的版本和ngrx/store的版本是否一致,如果不一致升级angular,

ng update @angular/core@17.0.0 --force。最好是删除node_modules目录重新下载。保证安装正常,版本一致

二 创建store目录,并且创建如下几个文件:

(1)actions.ts

(2) reducers.ts

(3) state.ts

复制代码
//state.ts

export interface AppState{
    count:number;
}   


//actions.ts
export const INSCRES="INSCRES"
export const DESCRES="DESCRES"
export const RESET="RESET"


//reduces:

import {Action} from "@ngrx/store"
import {INSCRES,DESCRES,RESET} from "./actions"

const initalState=0;
export function counterReducer(state:number=initalState,action:Action){

    switch(action.type){
            case INSCRES:
                return state+1;
            case DESCRES:
                return state-1
            case RESET:
                return 0
            default:
                return state
    }

}

(4) 页面中注入:注意angular中使用store和react稍有不同。没有createStore(reducer)然后根组件注入的过程,而是在具体页面里直接注入到constructor中,我们以news页面为例,

复制代码
import { Component, ElementRef, ViewChild } from '@angular/core';
import {INSCRES,DESCRES,RESET} from "../../store/reducer"
import {Store,select} from "@ngrx/store"
import { Observable } from 'rxjs';


interface AppState{
  count:number
}

@Component({
  selector: 'app-news',
  templateUrl: './news.component.html',
  styleUrls: ['./news.component.less']
})

export class NewsComponent {
 
  count:Observable<number>

  constructor(public http:HttpClient,private store:Store<AppState>){
      let stream=store.pipe(select('count'))
      stream.subscribe(res=>{
        console.log("res:",res)
      })
      this.count=store.pipe(select('count'))
  }

  increasement(){
    this.store.dispatch({type:INSCRES})
  }
  
  decreasement(){
    this.store.dispatch({type:DESCRES})
  }
  reset(){
    this.store.dispatch({type:RESET})

  }


}

然后在具体的页面中使用count:

复制代码
 <button (click)="increasement()">增加increase</button>
    <div>counter :{{count | async }}</div>
    <button (click)="decreasement()">减少increase</button>
    <button (click)="reset()">reset counter</button>

整体来看和react中使用redux并没有太大的差异。唯一的差异就是在react中需要定义store(let store=createStore(state,)),angular中直接通过在页面中注入的方式完成。

二:actions也可以是函数,我们可以改造下actions

复制代码
//actions :注意这里需要用Injectable
import {Injectable} from "@angular/core"

export const INSCRES="INSCRES"
export const DESCRES="DESCRES"
export const RESET="RESET"


@Injectable()
export  class CountAction{

    add(){
        return {
            type:INSCRES
        }
    }


}

此时我们需要向app.moudule.ts中作相应修改:

复制代码
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import {CountAction} from "./store/actions"


import { AppComponent } from './app.component';
import { NZ_I18N } from 'ng-zorro-antd/i18n';
import { zh_CN } from 'ng-zorro-antd/i18n';



import { HomeComponent } from './pages/home/home.component';
import { AppRouteModule } from './app-route.module';

import { StoreModule } from '@ngrx/store';

registerLocaleData(zh);

@NgModule({
    declarations: [
        AppComponent,
        LayoutComponent,
        HomeComponent,
        
    ],
    providers: [
        {provide:CountAction},
        { provide: [NZ_I18N, UrlSerializer], useValue: zh_CN },
        { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptorInterceptor, multi: true },
    ],
    bootstrap: [AppComponent],
    imports: [
        BrowserModule,
        FormsModule,
        AppRouteModule,
        StoreModule.forRoot({count:counterReducer}, {}),
    ]
})
export class AppModule { }

注意这里我们给providers添加了counterAction,以便在所有页面都可以注入countActions

回到页面本身:

复制代码
import { Component, OnInit } from '@angular/core';
import { Observable, Observer } from 'rxjs';
import{CountAction} from "../../store/actions"
import {Store,select} from "@ngrx/store"

interface AppState{
  count:number
}

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.less']
})
export class HomeComponent {
  
  count:Observable<number>

  constructor(private store:Store<AppState>,private action:CountAction){
    this.count=this.store.pipe(select('count'))


  increasement(){
    
    this.store.dispatch(this.action.add())
  }


}

这里逻辑的实现和之前一致,唯一的区别就是我们countAction直接注到了counstor里,然后在具体的执行函数中直接actiions的方法。

相关推荐
sycmancia35 分钟前
Qml——Window元素使用
前端
每天都好困43 分钟前
03 AR 投影与误差修正:把地图上的点贴到视频画面上
前端
每天都好困1 小时前
04 地图图层封装:像管理 Photoshop 图层一样管理地图元素
前端
去伪存真1 小时前
构建你的第一个 DevOps AI Agent:自动化捕获、分析并修复 CI 故障
前端·agent
niucloud-admin1 小时前
JAVA V6 多商户商城 开发文档——手机端前端
java·开发语言·前端
喵个咪1 小时前
GoWind Admin|风行 — 开箱即用的企业级全栈中后台框架:脚本系统实战
javascript·后端·go
樱花落木兰1 小时前
SpringBoot + ECharts 后台数据统计报表模块实战
java·javascript·spring boot·ai·log4j·github·echarts
skywalk81631 小时前
deepseekharness在对话中,有四种模式,分别是极简、PTC、创造和标准模式,每种模式下挂载的插件、skill等数量不一样
前端·人工智能·实践
愛芳芳2 小时前
element-plus+vite+vue3+pinpa+mock+typeScript搭建经典的电商管理后台
前端·javascript·typescript
liangshanbo12152 小时前
面试题:常见的前端构建工具有哪些?分别适用于什么场景?
前端