NgRx/Store 4 + Angular 5使用教程
这篇文章将会示范如何使用NgRx/Store 4和Angular5。@ngrx/store
是基于RxJS的状态管理库,其灵感来源于Redux。在NgRx中,状态是由一个包含action和reducer的函数的映射组成的。Reducer函数经由action的分发以及当前或初始的状态而被调用,最后由reducer返回一个不可变的状态。你可以在@ngrx/store
中找到我们将在下面的例子中讨论到的相关的API。
Action: Action
是状态的改变。它描述了某个事件的发生,但是没有指定应用的状态如何改变。
ActionReducerMap: ActionReducerMap
注册了一系列的reducer,在应用中使用StoreModule
对它进行配置。
ActionReducer: 它被用于创建reducer,例如logger。
MetaReducer: 在应用中使用StoreModule
配置的MetaReducer
构成了根的meta-reducer。
StoreModule: StoreModule
是@ngrx/store
API中的一个模块,它被用来在应用模块中配置reducer。
createFeatureSelector: 它为状态(state)创建一个feature selector。
createSelector: 它创建一个selector用于生成一个指定的状态。
Store: 它提供了Store.select()
和Store.dispatch()
来与reducer协同工作。Store.select()
用于选择一个selector,Store.dispatch()
用于向reducer分发action的类型。
1. 使用到的技术
下面是我们的例子中用到的技术:
- Angular 5.0.0
- Angular CLI 1.5.0
- NgRx/Store 4.1.1
- TypeScript 2.4.2
- Node.js 6.11.0
- NPM 3.10.10
2. 安装Angular CLI和NgRX/Store
- 确保已安装的Node和NPM的最低版本为:Node 6.9.x和NPM 3.x.x
- 在命令行中输入以下命令:
npm install -g @angular/cli
- 运行以下命令生成一个新的项目:
ng new my-app
- 现在安装
@ngrx/store
。使用命令行进入my-app
目录,然后运行如下命令:
npm i @ngrx/store --save
现在我们已经准备好使用NgRx/Store和Angular了。
3. 创建State
State是一个单独的不可变的数据结构。我们会像如下这样创建state:
export interface AppState {
articleState: ArticleState;
}
export interface ArticleState {
articles: Article[];
}
4. 创建Action类
NgRx的Action
描述了状态的变化。对于每一个action,我们都需要创建一个继承自Action
的类,同时定义其type和payload(payload是个可选参数)。
export const JAVA = 'Java';
export const MY_ARTICLES = 'Favorite_Articles';
export class JavaArticlesAction implements Action {
readonly type = JAVA;
}
export class FavoriteArticlesAction implements Action {
readonly type = MY_ARTICLES;
constructor(public payload: Article[]) {}
}
5. 创建Reducer
Reducer描述了任何一个action所对应的应用的state将怎样变化。reducer创建如下:
export function reducer(state = initialState, action: fromActions.All): ArticleState {
switch(action.type) {
case fromActions.JAVA: {
return {articles: JAVA_ARTICLES};
}
case fromActions.ANGULAR: {
return {articles: ANGULAR_ARTICLES};
}
case fromActions.MY_ARTICLES: {
return {articles: action.payload};
}
default: {
return state;
}
}
}
6. 使用createFeatureSelector和createSelector()
createFeatureSelector()
被用于为任意指定的state创建一个feature selector。
export const getArticleState = createFeatureSelector<ArticleState>('articleState');
createSelector()
使用feature selector来创建selector。
export const getArticles = createSelector(
getArticleState,
(state: ArticleState) => state.articles
);
7. 使用ActionReducerMap
ActionReducerMap
注册了reducer。我们需要在我们配置我们的reducer的地方创建一个 ActionReducerMap
的常量。然后在应用模块中使用StoreModule
来配置这个常量。
export const reducers: ActionReducerMap<AppState> = {
articleState: articleReducer.reducer
};
8.使用ActionReducer
ActionReducer
用来创建类似logger的reducer,使用MetaReducer
对它进行配置。
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);
};
}
通过使用上面的代码,我们可以在控制台中获取每个action的状态和名称。
9.使用MetaReducer
MetaReducer
由我们所创建的一系列ActionReducer
所组成。在应用中使用StoreModule
配置的MetaReducer
构成了根meta-reducer。@ngrx/store
默认使用 combineReducers
在创建根meta-reducer。
export const metaReducers: MetaReducer<AppState>[] = !environment.production
? [logger]
: [];
10. 使用StoreModule
StoreModule
是@ngrx/store
API中的一个模块,它被用来在应用模块中配置reducer。
@NgModule({
imports: [
---
StoreModule.forRoot(reducers, {metaReducers})
]
---
})
11. 使用Store.select()
和Store.dispatch()
Store.select()
和 Store.dispatch()
与是reducer配合使用的。Store.select()
用于选择一个selector,Store.dispatch()
用于向reducer分发action的类型。
要使用Store
, 在组件中创建一个Observable
类型的属性。
articles: Observable<Article[]>
现在使用依赖注入来实例化Store
,然后选择一个selector。
constructor(private store: Store<ArticleState>) {
this.articles = store.select(articleReducer.getArticles);
}
现在分发这个action以通过reducer改变state。
showJavaArticles(){
this.store.dispatch(new fromActions.JavaArticlesAction());
}
12. 完整的例子
下面是我们的例子的项目结构:
my-app
|
|--src
| |
| |--app
| | |
| | |--actions
| | | |
| | | |--article.actions.ts
| | |
| | |--components
| | | |
| | | |--article.component.html
| | | |--article.component.ts
| | |
| | |--models
| | | |
| | | |--article.ts
| | |
| | |--reducers
| | | |
| | | |--app.states.ts
| | | |--article.reducer.ts
| | | |--reducers.ts
| | |
| | |--app.component.ts
| | |--app.module.ts
| |
| |--main.ts
| |--index.html
| |--styles.css
|
|--node_modules
|--package.json
以下是完整的代码:
article.actions.ts
import { Action } from '@ngrx/store';
import { Article } from '../models/article';
export const JAVA = 'Java';
export const ANGULAR = 'Angular';
export const MY_ARTICLES = 'Favorite_Articles';
export class JavaArticlesAction implements Action {
readonly type = JAVA;
}
export class AngularArticlesAction implements Action {
readonly type = ANGULAR;
}
export class FavoriteArticlesAction implements Action {
readonly type = MY_ARTICLES;
constructor(public payload: Article[]) {}
}
export type All = JavaArticlesAction | AngularArticlesAction | FavoriteArticlesAction;
article.ts
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'}
]
app.states.ts
import { Article } from '../models/article';
export interface AppState {
articleState: ArticleState;
}
export interface ArticleState {
articles: Article[];
}
article.reducer.ts
import { createFeatureSelector, createSelector } from '@ngrx/store';
import * as fromActions from '../actions/article.actions';
import { JAVA_ARTICLES, ANGULAR_ARTICLES } from '../models/article';
import { ArticleState } from './app.states';
export const initialState: ArticleState = { articles: []};
export function reducer(state = initialState, action: fromActions.All): ArticleState {
switch(action.type) {
case fromActions.JAVA: {
return {articles: JAVA_ARTICLES};
}
case fromActions.ANGULAR: {
return {articles: ANGULAR_ARTICLES};
}
case fromActions.MY_ARTICLES: {
return {articles: action.payload};
}
default: {
return state;
}
}
}
export const getArticleState = createFeatureSelector<ArticleState>('articleState');
export const getArticles = createSelector(
getArticleState,
(state: ArticleState) => state.articles
);
reducer.ts
import { ActionReducerMap, ActionReducer, MetaReducer } from '@ngrx/store';
import { AppState } from './app.states';
import * as articleReducer from './article.reducer';
import { environment } from '../../environments/environment';
export const reducers: ActionReducerMap<AppState> = {
articleState: articleReducer.reducer
};
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]
: [];
article.component.ts
import { Store } from '@ngrx/store';
import { Component } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import * as articleReducer from '../reducers/article.reducer';
import * as fromActions from '../actions/article.actions';
import { ArticleState } from '../reducers/app.states';
import { Article, FAVORITE_ARTICLES } from '../models/article';
@Component({
selector: 'app-article',
templateUrl: 'article.component.html'
})
export class ArticleComponent {
articles: Observable<Article[]>
constructor(private store: Store<ArticleState>) {
this.articles = store.select(articleReducer.getArticles);
}
showJavaArticles(){
this.store.dispatch(new fromActions.JavaArticlesAction());
}
showAngularArticles(){
this.store.dispatch(new fromActions.AngularArticlesAction());
}
showFavoriteArticles(){
this.store.dispatch(new fromActions.FavoriteArticlesAction(FAVORITE_ARTICLES));
}
}
article.component.html
<button (click)="showJavaArticles()">Java Articles</button>
<button (click)="showAngularArticles()">Angular Articles</button>
<button (click)="showFavoriteArticles()">Favorite Articles</button>
<ul>
<li *ngFor="let article of articles | async">
{{article.id}} - {{article.title}} - {{article.category}}
</li>
</ul>
app.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
<app-article></app-article>
`
})
export class AppComponent {
}
app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { StoreModule } from '@ngrx/store';
import { AppComponent } from './app.component';
import { ArticleComponent } from './components/article.component';
import { reducers, metaReducers } from './reducers/reducers';
@NgModule({
imports: [
BrowserModule,
StoreModule.forRoot(reducers, {metaReducers})
],
declarations: [
AppComponent,
ArticleComponent
],
providers: [
],
bootstrap: [
AppComponent
]
})
export class AppModule { }
原文地址:NgRx/Store 4 + Angular 5 Tutorial
本文由本人原创翻译,转载请注明出处:https://www.jianshu.com/p/c2d61fc76128
NgRx/Store 4 + Angular 5使用教程的更多相关文章
- [Angular 2] ngrx/store
@ngrx/store builds on the concepts made popular by Redux and supercharges it with the backing of RxJ ...
- [Angular 2] Using ngrx/store and Reducers for Angular 2 Application State
ngrx/store is a library that simplifies common RxJS patterns for managing state and gives you an eas ...
- Angular应用架构设计-3:Ngrx Store
这是有关Angular应用架构设计系列文章中的一篇,在这个系列当中,我会结合这近两年中对Angular.Ionic.甚至Vuejs等框架的使用经验,总结在应用设计和开发过程中遇到的问题.和总结的经验, ...
- ngrx/store effects 使用总结1:计数器
本教程案例github:https://github.com/axel10/ngrx_demo-counter-and-list angular2+ 的学习成本应该是三大框架中最高的一个,教程及案例稀 ...
- [Angular] Extract Implementation Details of ngrx from an Angular Application with the Facade Pattern
Extracting away the implementation details of ngrx from your components using the facade pattern cre ...
- ngrx/store effects 使用总结2:列表展示
第一个计数器案例:http://www.cnblogs.com/axel10/p/8589122.html 完成了计数器案例后,现在开始比较能够完整的展示angular2+开发流程的案例:在线获取用户 ...
- Angular CLI 使用教程指南参考
Angular CLI 使用教程指南参考 Angular CLI 现在虽然可以正常使用但仍然处于测试阶段. Angular CLI 依赖 Node 4 和 NPM 3 或更高版本. 安装 要安装Ang ...
- [Angular2] @Ngrx/store and @Ngrx/effects learning note
Just sharing the learning experience related to @ngrx/store and @ngrx/effects. In my personal opinio ...
- Angular 英雄示例教程
英雄指南教程(Tour of Heroes)涵盖了 Angular 的基本知识. 在本教程中,你将构建一个应用,来帮助人事代理机构来管理一群英雄. 这个入门级 app 包含很多数据驱动的应用所需的特性 ...
随机推荐
- char数组中除去某个元素
/* 本程序说明: char数组中除去某个元素(其实就是strcpy源码的变形) */ #include <iostream> #include <cassert> #incl ...
- 1.12 dict 字典表
dict 字典表属于映射分类 dict的声明 >>> #dict类型 是 {}中包含若干个键值对 >>> d = dict() >>> d = { ...
- 1.3 fractions模块
数学世界中,浮点数还可以用分数形式展示,不可约简的分数形式往往更简洁直观. 问题来了,Python中如何输出不可约简的分数形式呢? 答案:用Fraction类来实现.这个类属于标准库的fracti ...
- ContentProvider工作过程
ContentProvider启动过程(通过query方法触发) ContentProvider.acquireProvider--> ApplicationContentResolver.ac ...
- java网络编程(5)——Tcp
Tcp相对于Udp就是面向连接的协议,最主要的特点要建立连接之后才能通信,客户端用Socket需要指点地址与端口,服务端用ServeSocket,只需指点监听某个端口,因为是面向连接,所以服务器端一定 ...
- spring boot admin + spring boot actuator + erueka 微服务监控
关于spring boot actuator简单使用,请看 简单的spring boot actuator 使用,点击这里 spring boot admin 最新的正式版本是1.5.3 与 spri ...
- Linux下用户和组管理
用户与组之间的关系是,组下面有若干个用户,每个用户必须从属于唯一一个组.组可以理解为权限的集合.用户管理的命令有:useradd, userdel, usermod, passwd, chsh, ch ...
- linux主机名为bogon的原因及修改方法
今天登录linux,发现主机名是bogon,虽然不影响使用,但是看着很不爽,于是想了解一下,为什么会发生这种情况,在csdn上找了到了一个文章,原文如下: 起因:公司网络接口做了接口认证,虚拟机桥接至 ...
- javascript垃圾收集与性能问题
一.垃圾收集 JavaScript具有自动垃圾收集功能,也就是说,执行环境会负责管理代码所占用的内存. 不同于C和类C语言,这些语言都需要手动监听内存的使用情况.JavaScript实现了自动管理内存 ...
- Dijkstra and Floyd算法
Dijkstra算法 算法思想:设G=(V,E)是一个带权有向图,把图中顶点集合V分成两组,第一组为已求出最短路径的顶点集合(用S表示,初始时S中只有一个源点,以后每求得一条最短路径 , 就将加入到集 ...