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的方法。

相关推荐
风吹落叶花飘荡5 分钟前
2025 Next.js项目提前编译并在服务器
服务器·开发语言·javascript
加减法原则5 分钟前
Vue3 组合式函数:让你的代码复用如丝般顺滑
前端·vue.js
yanlele38 分钟前
我用爬虫抓取了 25 年 6 月掘金热门面试文章
前端·javascript·面试
lichenyang45342 分钟前
React移动端开发项目优化
前端·react.js·前端框架
天若有情67344 分钟前
React、Vue、Angular的性能优化与源码解析概述
vue.js·react.js·angular.js
你的人类朋友1 小时前
🍃Kubernetes(k8s)核心概念一览
前端·后端·自动化运维
web_Hsir1 小时前
vue3.2 前端动态分页算法
前端·算法
烛阴1 小时前
WebSocket实时通信入门到实践
前端·javascript
草巾冒小子1 小时前
vue3实战:.ts文件中的interface定义与抛出、其他文件的调用方式
前端·javascript·vue.js
DoraBigHead2 小时前
你写前端按钮,他们扛服务器压力:搞懂后端那些“黑话”!
前端·javascript·架构