完全基于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.tsexport 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-1case RESET:return 0default: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的方法。