创建 @ngrx 4.x 项目

@ngrx 4.x 相比上一个版本有了一些变化,该文介绍了如何在 Angular 中集成 @ngrx r.x 实现状态管理。

一、创建基本项目

使用 Angular CLI 创建项目

执行 ng new hello 创建 Angular 项目

添加 @ngrx 包

至少添加两个包:

  • @ngrx/store
  • @ngrx/store-devtools

第一个是 @ngrx 的核心包,第二个是与浏览器工具插件配合的包,你可以从这里下载 chrome 的 devtools.

目前它们的版本分别是:

"@ngrx/store": "4.1.0",
"@ngrx/store-devtools": "4.0.0",

执行命令:

npm i @ngrx/store @ngrx/store-devtools -S

之后,你应该在 package.json 中看到这两个包的定义。

二、基本示例

1. 创建计数器的 reducer。

它接受三种 action,我们使用字符串常量来分别表示

  • INCREMENT    增加
  • DECREMENT   减少
  • RESET             重置

这里的状态就是一个基本类型的 number,默认值为 0。

import { Action } from '@ngrx/store';

export const INCREMENT = 'INCREMENT';
export const DECREMENT = 'DECREMENT';
export const RESET = 'RESET'; export function counterReducer(state: number = 0, action: Action) {
switch (action.type) {
case INCREMENT:
return state + 1; case DECREMENT:
return state - 1; case RESET:
return 0; default:
return state;
}
}

2. 注册 reducer

在这个示例中,我们仅仅拥有一个计数器的 reducer,所以只需要注册它自己。

在 ngrx 4.x 中,应用需要在根模块中使用 StoreModule.forRoot 来注册根 reducer。该方法可以接收两个参数

  • 表示 reducer 的 ActionReducerMap对象,使用它,我们可以将多个 reducer 聚合起来。
  • 一个可选的配置对象,其中可选的名为 initialState 表示初始状态的对象,此对象的结构需要与第一个参数对应。

在这个示例中,第一个参数被表示成了一个 ActionReducerMap 对象。

{ counter: counterReducer }

这里没有提供初始状态。如果提供的话,结构必须与前面的 ActionReducerMap 结构相同。比如:

StoreModule.forRoot({ counter: counterReducer }, { initialState: { counter: 9 } }),

下面是官方的示例源码

import { NgModule } from '@angular/core'
import { StoreModule } from '@ngrx/store';
import { counterReducer } from './counter'; @NgModule({
imports: [
BrowserModule,
StoreModule.forRoot({ counter: counterReducer }),
StoreDevtoolsModule.instument({maxAge: 50 })
]
})
export class AppModule {}

高亮行为启用 Redux Dev tools 支持,以便在浏览器工具中查看状态。

3. 使用 Store

使用 Store 的 select 方法可以从 Store 中选取状态数据。在这个示例中,Store 的结构为一个对象,其中 counter 表示我们的计数状态,见前面 2 的定义。

我们可以将它读取出来,读取的结果是一个 Observable 对象

this.counter = store.select('counter');

因此,在模板中需要使用 async 将它的值订阅出来。

改变 Store 的状态使用 Action,通过调用 Store 的 dispatch 方法来改变 Store 的状态。

import { Store } from '@ngrx/store';
import { Observable } from 'rxjs/Observable';
import { INCREMENT, DECREMENT, RESET } from './counter';
import { Component } from '@angular/core'; interface AppState {
counter: number;
} @Component({
selector: 'app-root',
template: `
<button (click)="increment()">Increment</button>
<div>Current Count: {{ counter | async }}</div>
<button (click)="decrement()">Decrement</button> <button (click)="reset()">Reset Counter</button>
`
})
export class MyAppComponent {
counter: Observable<number>; constructor(private store: Store<AppState>) {
this.counter = store.select('counter');
} increment() {
this.store.dispatch({ type: INCREMENT });
} decrement() {
this.store.dispatch({ type: DECREMENT });
} reset() {
this.store.dispatch({ type: RESET });
}
}

4. 运行应用

运行应用,点击增加、减少按钮,观察状态的变化。

启动浏览器插件 Dev Tools。观察状态的变化。

三、创建使用功能模块划分状态

在 Angular 中,可以使用模块来划分应用。

在功能模块中,我们使用 StoreModule.forFeature 来注册 reducer, 在这个方法中,我们需要提供一个字符串作为这个功能模块的 Key, 这部分状态将在功能模块被加载的时候附加到全局状态上。

import { NgModule } from '@angular/core'
import { StoreModule } from '@ngrx/store';
import { counterReducer } from './counter'; @NgModule({
imports: [
StoreModule.forFeature('feature', { counter: counterReducer })
]
})
export class CounterModule {}

参见:Feature Module State Composition

四、使用 combineReducers 自由组合 reducer

可以使用 redux 中经典的 combineReducers 函数自由组合 recuders,以便构建自定义的状态结构。

但是,由于 AOT 的原因,会导致无法通过 AOT 检测。

使用注入根 reducer 的方法是来完成。

这种方式需要定义一个 Token,然后通过 provider 来完成根 reducer 的注册。而不是 StoreModule.forRoot() 函数。

1. 定义 Token

使用标准方式定义 Token,你需要提供一个 Token 的名称。

export const REDUCER_TOKEN = new InjectionToken<ActionReducerMap<fromRoot.State>>('Registered Reducers');

2. 定义工厂函数

定义一个返回根 reducer 的工厂函数,这个函数甚至可以依赖某个服务,这样的化,还需要在 prodiver 中提供这个服务的依赖。

export function getReducers(someService: SomeService) {
return someService.getReducers();
}

3. 通过 provider 完成注册

这里的 deps 是因为上面的示例中,使用了这个 SomeService 服务。

providers: [
{
provide: REDUCER_TOKEN,
deps: [SomeService],
useFactory: getReducers
}
]

完整的代码

import { NgModule, InjectionToken } from '@angular/core';
import { StoreModule, ActionReducerMap } from '@ngrx/store'; import { SomeService } from './some.service';
import * as fromRoot from './reducers'; export const REDUCER_TOKEN = new InjectionToken<ActionReducerMap<fromRoot.State>>('Registered Reducers'); export function getReducers(someService: SomeService) {
return someService.getReducers();
} @NgModule({
imports: [
StoreModule.forRoot(REDUCER_TOKEN),
],
providers: [
{
provide: REDUCER_TOKEN,
deps: [SomeService],
useFactory: getReducers
}
]
})
export class AppModule { }

参见:Injecting Reducers

五、其它资料:

ngrx 4: 创建 ngrx 4.x 项目的更多相关文章

  1. 用Kotlin创建第一个Android项目(KAD 01)

    原文标题:Create your first Android project using Kotlin (KAD 01) 作者:Antonio Leiva 时间:Nov 21, 2016 原文链接:h ...

  2. IntelliJ IDEA上创建maven Spring MVC项目

    IntelliJ IDEA上创建Maven Spring MVC项目 各软件版本 利用maven骨架建立一个webapp 建立相应的目录 配置Maven和SpringMVC 配置Maven的pom.x ...

  3. 3.创建第一个android项目

    安卓开发学习笔记 1.安卓开发之环境搭建 2.SDK目录结构和adb工具及命令介绍 3.创建第一个android项目 1.打开Eclipse,选择File——>new——>others.. ...

  4. soapui中文操作手册(一)----创建一个新的项目

    1) 创建一个新的项目 点击项目,选择新建项目SOAP.这将打开一个新的SOAP项目对话框. 注意:你也可以做CTRL + N(WIN)或CMD+ N(MAC)来创建一个新的SOAP项目. 在新的SO ...

  5. step2-------使用myeclipse创建maven java web项目

    1.文章内容概述: 在对项目需求进行分析之后,决定使用maven对我的java web项目进行管理,这篇文章记录了使用myeclipse创建maven java web项目的过程. 2.开发环境: j ...

  6. 在 Visual Studio 2013 中创建 ASP.NET Web 项目(0):专题导航 [持续更新中]

    写在前面的话 随着 Visual Studio 2013 的正式推出,ASP.NET 和 Visual Studio Web 开发工具 也发布了各自的最新版本. 新版本在构建 One ASP.NET ...

  7. 在 Visual Studio 2013 中创建 ASP.NET Web 项目(1):概述 - 创建 Web 应用程序项目

    注:本文是“在 Visual Studio 2013 中创建 ASP.NET Web 项目”专题的一部分,详情参见 专题导航 . 预备知识 本专题适用于 Visual Studio 2013 及以上版 ...

  8. 如何用Maven创建一个普通Java项目

    一下内容包括:用Maven创建一个普通Java项目,并把该项目转成IDEA项目,导入到IDEA,最后把这个项目打包成一个jar文件. 有时候运行mvn命令失败,重复运行几次就OK了,无解(可能因为网络 ...

  9. [译]使用Babel和Browserify创建你的ES6项目

    原文地址:Setting up an ES6 Project Using Babel and Browserify JavaScript的发展日新月异,ES6很快就要接管JS了.很多著名的框架像Ang ...

  10. 从头开始编写一个Orchard网上商店模块(3) - 创建Orchard.Webshop模块项目

    原文地址:http://skywalkersoftwaredevelopment.net/blog/writing-an-orchard-webshop-module-from-scratch-par ...

随机推荐

  1. UEFI原理与编程(二)

    系统表 对UEFI应用程序和驱动程序开发人员来讲,系统表是最重要的数据结构之一,它是用户空间通往内核空间的通道.有了它,UEFI应用程序和驱动才可以访问UEFI内核.硬件资源和I/O设备. 1 在应用 ...

  2. KubeSphere 在互联网医疗行业的应用实践

    作者:宇轩辞白,运维研发工程师,目前专注于云原生.Kubernetes.容器.Linux.运维自动化等领域. 前言 2020 年我国互联网医疗企业迎来了"爆发元年",越来越多居民在 ...

  3. ArgoWorkflow教程(八)---基于 LifecycleHook 实现流水线通知提醒

    本篇介绍一下 ArgoWorkflow 中的 ExitHandler 和 LifecycleHook 功能,可以根据流水线每一步的不同状态,执行不同操作,一般用于发送通知. 1. 概述 本篇介绍一下 ...

  4. 【VMware VCF】使用 Offline Bundle Transfer Utility(OBTU)配置 VCF 脱机库。

    VMware Cloud Foundation 环境中,软件包仓库的来源支持两种方式,分别是 Online Depot 和 Offline Depot.第一种方式,是在 VCF 环境能够连接互联网的情 ...

  5. MongoDB聚合类操作

    MongoDB中聚合(aggregate)主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果.有点类似sql语句中的 count(*) 语法:db.tablename.aggregat ...

  6. 强化学习环境gym/gymnasium下的atari环境的v0、v4、v5的说明

    声明: 本文是最新版gym-0.26.2下Atari环境的安装以及环境版本v0,v4,v5的说明的部分更新和汇总,可以看作是更新和延续版本. 由于gym已经由openai公司独立出来,虽然开发团队和投 ...

  7. 基于Java+SpringBoot心理测评心理测试系统功能实现六

    一.前言介绍: 1.1 项目摘要 心理测评和心理测试系统在当代社会中扮演着越来越重要的角色.随着心理健康问题日益受到重视,心理测评和心理测试系统作为评估个体心理状态.诊断心理问题.制定心理治疗方案的工 ...

  8. 基于Java+SpringBoot+Mysql实现的快递柜寄取快递系统功能实现七

    一.前言介绍: 1.1 项目摘要 随着电子商务的迅猛发展和城市化进程的加快,快递业务量呈现出爆炸式增长的趋势.传统的快递寄取方式,如人工配送和定点领取,已经无法满足现代社会的快速.便捷需求.这些问题不 ...

  9. 用Java实现samza转换成flink

    将Apache Samza作业迁移到Apache Flink作业是一个复杂的任务,因为这两个流处理框架有不同的API和架构.然而,我们可以将Samza作业的核心逻辑迁移到Flink,并尽量保持功能一致 ...

  10. 使用wxpython开发跨平台桌面应用,基类列表窗体的抽象封装处理

    在开发一套系统框架的时候,除了关注实现系统的功能实现外,我们对于系统的各个方面都是应该精益求精,以最少的编码做最好的事情,在开发的各个层次上,包括前端后端,界面处理.后端处理.常用辅助类.控件封装等等 ...