Store
是受 Redux
启发的用于 Angular
应用程序的 RxJS
驱动的全局状态管理。Store
是一个受控状态容器,旨在帮助在Angular
之上编写高性能、一致的应用程序。
常规条件下构建Angular项目
- 运行命令
ng new angular-ngrx
- 进入到新创建的项目文件夹
cd angular-ngrx
- 通过VSCode打开项目
code .
- 执行
npm start
检查项目初始化是否正确
Angular常规情况下共享数据
对于Angular Component内或者Componenet之间,我们常规情况下通过
Service
来实现依赖注入并共享数据添加
ProductComponent
并实现新增、删除功能通过
ng g c product
来创建新的组件在
src/app
目录下新建目录models
,actions
,reducers
,states
,在
models
目录下新建product.model.ts
1
2
3
4export interface Product{
name:string;
price:number;
}修改
product.component.ts
实现数据加载,新增,删除1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28import { Component, OnInit } from '@angular/core';
import { Product } from '../models/product.model';
@Component({
selector: 'app-product',
templateUrl: './product.component.html',
styleUrls: ['./product.component.css']
})
export class ProductComponent implements OnInit {
products:Product[]
newProduct:Product = {name:'',price:0}
constructor() { }
ngOnInit() {
this.products = [
{name:'Product A', price:200},
{name:'Product B', price:300},
{name:'Product C', price:500},
]
}
addProduct(product:Product){
this.products.push(Object.assign({},product));
}
removeProduct(index:number){
this.products.splice(index, 1);
}
}修改
app.module.ts
添加FormsModule
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { ProductComponent } from './product/product.component';
import { FormsModule } from '@angular/forms';
@NgModule({
declarations: [
AppComponent,
ProductComponent
],
imports: [
FormsModule,
BrowserModule,
AppRoutingModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }修改
product.component.html
1
2
3
4
5
6
7
8<input [(ngModel)]="newProduct.name"/>
<input [(ngModel)]="newProduct.price"/>
<button (click)="addProduct(newProduct)">新增</button>
<ul>
<li *ngFor="let product of products;let i = index">
{{ product.name }} {{product.price}} <button (click)="removeProduct(i)">删除</button>
</li>
</ul>测试界面,可以实现简单的新增,删除,这里的新增删除都是通过
products
变量来管理的,如果我们想跨组件新增,删除,获取products
就没有办法实现通过Ngrx来管理Angular项目的数据
Ngrx通过
Store
来管理并在组件间共享数据的状态我们通过
Store
、Action
、Reduer
来改写上面的常规共享数据执行命令
npm install @ngrx/store
安装ngrx
在
actions
文件夹下新建product.action.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21import { Action } from "@ngrx/store";
import { Product } from "../models/product.model";
export const enum ProductActionType {
ProductAdd = '[Product Component] Product Add',
ProductRemove = '[Product Component] Product Remove'
}
export class ProductAddAction implements Action{
type = ProductActionType.ProductAdd;
constructor(payload:Product){}
}
export class ProductRemoveAction implements Action{
type = ProductActionType.ProductRemove;
constructor(payload:number){}
}
export type ProductActions =
ProductAddAction |
ProductRemoveAction;在
reducers
目录下创建product.reducer.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19import { ProductActions, ProductActionType } from "../actions/product.action";
import { Product } from "../models/product.model";
export const initialProductState:Product[] =[
{name:'Product A', price:200},
{name:'Product B', price:300},
{name:'Product C', price:500}
]
export function ProductReducer(state:Product[] = initialProductState, action:ProductActions){
switch(action.type){
case ProductActionType.ProductAdd:
return [...state, Object.assign({},action.payload) ];
case ProductActionType.ProductRemove:
state.splice(action.payload,1);
return state;
default:
return state;
}
}修改
app.module.ts
注册StoreModule
1
2
3
4
5
6imports: [
FormsModule,
BrowserModule,
AppRoutingModule,
StoreModule.forRoot({products:ProductReducer})
],更新
product.component.ts
以启用Store
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33import { Component, OnInit } from '@angular/core';
import { Store } from '@ngrx/store';
import { ProductAddAction, ProductRemoveAction } from '../actions/product.action';
import { Product } from '../models/product.model';
@Component({
selector: 'app-product',
templateUrl: './product.component.html',
styleUrls: ['./product.component.css']
})
export class ProductComponent implements OnInit {
products: Product[]
newProduct:Product = {name:'',price:0}
constructor(private productStore:Store<{products:Product[]}>) { }
ngOnInit() {
// this.products = [
// {name:'Product A', price:200},
// {name:'Product B', price:300},
// {name:'Product C', price:500},
// ]
this.productStore.select('products').pipe().subscribe((data:Product[]) => this.products = data);
}
addProduct(product:Product){
//this.products.push(Object.assign({},product));
this.productStore.dispatch(new ProductAddAction(product));
}
removeProduct(index:number){
//this.products.splice(index, 1);
this.productStore.dispatch(new ProductRemoveAction(index));
}
}引入
State
来管理对象的多个属性在
states
目录下创建product.state.ts
1
2
3
4
5import { Product } from "src/app/models/product.model";
export interface ProductState{
products:Product[]
}修改
product.reducer.ts
创建createFeatureSelector
和createSelector
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27import { createFeatureSelector, createSelector } from "@ngrx/store";
import { ProductState } from "src/state/product.state";
import { ProductActions, ProductActionType } from "../actions/product.action";
import { Product } from "../models/product.model";
export const productFeatureState = createFeatureSelector<ProductState>('productState');
export const productState = createSelector(
productFeatureState,
state => state.products
)
export const initialProductState:Product[] =[
{name:'Product A', price:200},
{name:'Product B', price:300},
{name:'Product C', price:500}
]
export function ProductReducer(state:Product[] = initialProductState, action:ProductActions){
switch(action.type){
case ProductActionType.ProductAdd:
return [...state, Object.assign({},action.payload) ];
case ProductActionType.ProductRemove:
state.splice(action.payload,1);
return state;
default:
return state;
}
}创建
product-action-reducer-map.ts
1
2
3
4
5
6
7import { ActionReducerMap } from "@ngrx/store";
import { ProductReducer } from "src/app/reducers/product.reducer";
import { ProductState } from "../state/product.state";
export const ProductActionReduerMap:ActionReducerMap<ProductState> = {
products: ProductReducer
}修改
app.module.ts
注入productFeatureState
1
2StoreModule.forFeature('productState', ProductActionReduerMap),
StoreModule.forRoot({})修改
product.component.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23export class ProductComponent implements OnInit {
products: Product[]
newProduct:Product = {name:'',price:0}
constructor(private productStore:Store<ProductState>) { }
ngOnInit() {
// this.products = [
// {name:'Product A', price:200},
// {name:'Product B', price:300},
// {name:'Product C', price:500},
// ]
//this.productStore.select('products').pipe().subscribe((data:Product[]) => this.products = data);
this.productStore.select(productState).pipe().subscribe((data:Product[]) => this.products = data);
}
addProduct(product:Product){
//this.products.push(Object.assign({},product));
this.productStore.dispatch(new ProductAddAction(product));
}
removeProduct(index:number){
//this.products.splice(index, 1);
this.productStore.dispatch(new ProductRemoveAction(index));
}
}FAQ
如果遇到错误
Cannot delete property '2' of [object Array]
- 通过命令
npm install @ngrx/store@8.5.2
安装"@ngrx/store": "^8.5.2"
- 通过命令
如果遇到错误
ERROR TypeError: Cannot assign to read only property '1' of object '[object Array]'
-
引用