1. Angular 8.0.2
2. Angular CLI 8.0.4
3. NgRx 8.0.1
4. TypeScript 3.4.5
5. Node.js 10.16.0
6. NPM 6.9.0
npm install @ngrx/store --save
1.新建article组件,在app.component中引用:
<app-article>app-article>
article组件中用三个按钮切换不同状态:
<button (click)="showJavaArticles()">Java Articlesbutton>
<button (click)="showAngularArticles()">Angular Articlesbutton>
<button (click)="showFavoriteArticles()">Favorite Articlesbutton>
<ul>
<li *ngFor="let article of articles | async">
{{article.id}} - {{article.title}} - {{article.category}}
li>
ul>
按钮对应不同的action点击事件:
@Component({
selector: 'app-article',
templateUrl: './article.component.html',
styleUrls: ['./article.component.css']
})
export class ArticleComponent implements OnInit {
articles: Observable<Article[]>
constructor(private store: Store<ArticleState>) {
this.articles = store.select(articleReducer.getArticles);
}
ngOnInit(): void {
}
showJavaArticles() {
this.store.dispatch(JavaArticlesAction());
}
showAngularArticles() {
this.store.dispatch(AngularArticlesAction());
}
showFavoriteArticles() {
this.store.dispatch(FavoriteArticlesAction({ articles: FAVORITE_ARTICLES }));
}
}
2.article state接口:
import { Article } from '../models/article';
export interface AppState {
articleState: ArticleState;
}
export interface ArticleState {
articles: Article[];
}
3.model存放数据:
export interface Article {
id: number;
title: string;
category: string;
}
export const JAVA_ARTICLES: Article[] = [
{id: 1, title: 'Java Article 1', category: 'Java'},
{id: 2, title: 'Java Article 2', category: 'Java'},
]
export const ANGULAR_ARTICLES: Article[] = [
{id: 1, title: 'Angular Article 1', category: 'Angular'},
{id: 2, title: 'Angular Article 2', category: 'Angular'},
]
export const FAVORITE_ARTICLES: Article[] = [
{id: 1, title: 'Java Article 1', category: 'Java'},
{id: 2, title: 'Angular Article 2', category: 'Angular'}
]
4.创建action,带参数和不带参数的:
import { createAction, props } from '@ngrx/store';
import { Article } from '../models/article';
export const JavaArticlesAction = createAction('Java');
export const AngularArticlesAction = createAction('Angular');
export const FavoriteArticlesAction = createAction('MyArticles', props<{ articles: Article[] }>());
5.通过createReducer创建reducer,这里还通过createSelector将得到的articleState进一步选择,得到articles
import { createReducer, on, createFeatureSelector, createSelector } from '@ngrx/store';
import { ArticleState } from './app.state';
import { JavaArticlesAction, AngularArticlesAction, FavoriteArticlesAction } from '../actions/aticle.action';
import { JAVA_ARTICLES, ANGULAR_ARTICLES } from '../models/article';
export const initialState: ArticleState = { articles: [] };
export const articleReducer = createReducer(initialState,
on(JavaArticlesAction, state => ({ articles: JAVA_ARTICLES })),
on(AngularArticlesAction, state => ({ articles: ANGULAR_ARTICLES })),
on(FavoriteArticlesAction, (state, action) => ({ articles: action.articles })),
);
export const getArticleState = createFeatureSelector<ArticleState>('articleState');
export const getArticles = createSelector(
getArticleState,
(state: ArticleState) => state.articles
);
6.metaReducer类似中间件,可以看做action-> reducer管道的钩子,通过 metaReducers configuration 选项可以提供 meta-reducers数组包含多个钩子,这里加入了一个logger处理:
import { ActionReducerMap, ActionReducer, MetaReducer } from '@ngrx/store';
import { AppState } from './app.state';
import * as articleReducer from './article.reducer';
import { environment } from '../../environments/environment';
export const reducers: ActionReducerMap<AppState> = {
articleState: articleReducer.articleReducer
};
export function logger(reducer: ActionReducer<AppState>): ActionReducer<AppState> {
return function(state: AppState, action: any): AppState {
console.log('state', state);
console.log('action', action);
return reducer(state, action);
};
}
export const metaReducers: MetaReducer<AppState>[] = !environment.production
? [logger]
: [];
7.将reducer和metaReducer注册到app.module:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { ArticleComponent } from './article/article.component';
import { StoreModule } from '@ngrx/store';
import { reducers, metaReducers } from './reducers/reducer';
@NgModule({
declarations: [
AppComponent,
ArticleComponent
],
imports: [
BrowserModule,
AppRoutingModule,
StoreModule.forRoot(reducers, { metaReducers })
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }