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

相关推荐
stoneship6 分钟前
Web项目减少资源加载失败白屏问题
前端
DaMu35 分钟前
Cesium & Three.js 【移动端手游“户外大逃杀”】 还在“画页面的”前端开发小伙伴们,是时候该“在往前走一走”了!我们必须摆脱“画页面的”标签!
前端·gis
非专业程序员35 分钟前
一文读懂Font文件
前端
Asort37 分钟前
JavaScript 从零开始(七):函数编程入门——从定义到可重用代码的完整指南
前端·javascript
Johnny_FEer38 分钟前
什么是 React 中的远程组件?
前端·react.js
真夜38 分钟前
关于rngh手势与Slider组件手势与事件冲突解决问题记录
android·javascript·app
我是日安41 分钟前
从零到一打造 Vue3 响应式系统 Day 10 - 为何 Effect 会被指数级触发?
前端·vue.js
知了一笑41 分钟前
「AI」网站模版,效果如何?
前端·后端·产品
艾小码44 分钟前
用了这么久React,你真的搞懂useEffect了吗?
前端·javascript·react.js
知觉44 分钟前
实现@imput支持用户输入最多三位整数,最多一位小数的数值
前端