ngrx/store effects 使用总结2:列表展示
第一个计数器案例:http://www.cnblogs.com/axel10/p/8589122.html
完成了计数器案例后,现在开始比较能够完整的展示angular2+开发流程的案例:在线获取用户列表并展示,包含点击删除功能。希望在开始之前,你对typescript和rxjs有一定了解。
再重复一遍开发流程:
开始 -> 编写数据模型 -> 编写action -> 编写redurces并配置到相应module -> 编写services -> 编写effects并配置到相应module -> 创建组件 -> 组件绑定数据模型 -> 渲染
第一步:编写数据模型(app/models/user.ts)
export class User {
id: number;
name: string;
}
第二步:编写action(app/actions/num.ts)
import {Action} from '@ngrx/store';
import {User} from '../models/user';
export enum ListActionType {
Load = 'LOAD',
LoadSuccess = 'LOAD_SUCCESS',
RemoveUser = 'REMOVE_USER',
RemoveUserSuccess = 'REMOVE_USER_SUCCESS',
RemoveUserError = 'REMOVE_USER_ERROR'
}
export class Load implements Action {
readonly type = ListActionType.Load;
}
export class LoadSuccess implements Action {
readonly type = ListActionType.LoadSuccess;
constructor(public payload: User[]) {
}
}
export class RemoveUser implements Action {
readonly type = ListActionType.RemoveUser;
constructor(public payload: number) {
}
}
export class RemoveUserSuccess implements Action {
readonly type = ListActionType.RemoveUserSuccess;
}
export class RemoveUserError implements Action {
readonly type = ListActionType.RemoveUserError;
}
第三步:编写redurcers(app/redurces/list.ts)
import {Action} from '@ngrx/store';
import {User} from '../models/user';
import {ListActionType, LoadSuccess, RemoveUser} from '../actions/list';
export interface State {
loading: boolean;
loaded: boolean;
list: User[];
}
const initialState: State = {
loading: false,
loaded: false,
list: []
};
export const list = (state = initialState, action: Action) => {
switch (action.type) {
case ListActionType.Load:
console.log('load....');
return {
...state,
loading: true,
};
case ListActionType.LoadSuccess:
console.log('load success');
const myA = (<LoadSuccess>action).payload;
console.log(myA);
return {
...state,
loaded: true,
loading: false,
list: myA
};
case ListActionType.RemoveUser:
console.log('remove user');
const userId = (<RemoveUser>action).payload;
state.list = state.list.filter(function (item) {
return item.id !== userId;
});
return {...state};
default:
return state;
}
};
配置redurcer(app/app.module.ts)
imports: [
BrowserModule,
RouterModule.forRoot(routes),
StoreModule.forRoot({ modelNum, list}), //配置redurcer
],
第四步:编写services(app/services/ListService.ts)
import {Injectable} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {Observable} from 'rxjs/Observable';
import {User} from '../models/user';
@Injectable()
export class ListService {
public getList(): Observable<any> {
return this.http.get<{ users: User[] }>('/api/users.json');
}
public removeUser(): Observable<any> {
return Observable.create(function (observer) {
observer.next('true');
});
}
constructor(private http: HttpClient) {
}
}
第五步:编写effects:
import {Injectable} from '@angular/core';
import {Actions, Effect, ofType} from '@ngrx/effects';
import {Observable} from 'rxjs/Observable';
import {Action} from '@ngrx/store';
import {ListActionType, Load, LoadSuccess, RemoveUser, RemoveUserError, RemoveUserSuccess} from '../actions/list';
import {catchError, map, switchMap} from 'rxjs/operators';
import {ListService} from '../services/ListService';
import {of} from 'rxjs/observable/of';
@Injectable()
export class ListEffects {
@Effect()
loadList$: Observable<Action> = this.action$.pipe( //rxjs写法。loadList$是effect名,在外部没有用到,可以随便起。
ofType<Load>(ListActionType.Load),
switchMap(action => {
return this.listService.getList().pipe(map(
users => {
return new LoadSuccess(users);
}
));
})
);
@Effect()
removeUser$: Observable<Action> = this.action$.pipe(
ofType<RemoveUser>(ListActionType.RemoveUser),
switchMap(_ => {
return this.listService.removeUser().pipe(
map(res => {
console.log(res);
if (res === 'true') {
return new RemoveUserSuccess();
} else {
return new RemoveUserError();
}
}),
catchError(err => of(new RemoveUserError()))
);
})
);
constructor(private action$: Actions, private listService: ListService) {
}
}
记得在app.module.ts配置effects和HttpClient:
imports: [
BrowserModule,
RouterModule.forRoot(routes),
StoreModule.forRoot({modelNum, list}),
EffectsModule.forRoot([ListEffects]),
HttpClientModule
],
第六步:创建组件
ng g component list
第七步:组件绑定数据模型(连带完成第八步)
组件ts文件:
import {Component, OnInit} from '@angular/core';
import {Store} from '@ngrx/store';
import * as list from '../actions/list';
import {State} from '../reducers/list';
import {User} from '../models/user';
@Component({
selector: 'app-list',
templateUrl: './list.component.html',
styleUrls: ['./list.component.scss']
})
export class ListComponent implements OnInit {
public list: User[];
constructor(private store: Store<any>) {
this.store.select('list').subscribe(_list => {
if (_list) {
console.log(_list);
console.log(_list.list);
this.list = _list.list;
}
});
}
removeUser(id) {
console.log(id);
this.store.dispatch(new list.RemoveUser(id));
}
ngOnInit() {
this.store.dispatch(new list.Load());
}
}
组件html文件:
<div>
list
请尝试点击上半部分的li。
<ul>
<li *ngFor="let item of list" (click)="removeUser(item.id)">{{item.name}}</li>
</ul>
<app-list-body></app-list-body>
<br/>
<a routerLink="/model">to counter demo</a>
</div>
最后配置路由:
import {Routes} from '@angular/router';
import {IndexComponent} from './index/index.component';
import {ModelDemoComponent} from './model-demo/model-demo.component';
import {ListComponent} from './list/list.component';
export const routes: Routes = [
{
path: 'list',
component: ListComponent
},
{
path: 'model',
component: ModelDemoComponent
},
{
path: '**',
redirectTo: 'list'
}
];
到此本案例结束。如果想要更加复杂的案例可以到ngrx的github获取。https://github.com/ngrx/platform
ngrx/store effects 使用总结2:列表展示的更多相关文章
- ngrx/store effects 使用总结1:计数器
本教程案例github:https://github.com/axel10/ngrx_demo-counter-and-list angular2+ 的学习成本应该是三大框架中最高的一个,教程及案例稀 ...
- [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应用架构设计-3:Ngrx Store
这是有关Angular应用架构设计系列文章中的一篇,在这个系列当中,我会结合这近两年中对Angular.Ionic.甚至Vuejs等框架的使用经验,总结在应用设计和开发过程中遇到的问题.和总结的经验, ...
- Vuex 教程案例:计数器以及列表展示
本案例github:https://github.com/axel10/Vuex_demo-Counter-and-list 本篇教程将以计数器及列表展示两个例子来讲解Vuex的简单用法. 从安装到启 ...
- Winform开发主界面菜单的动态树形列表展示
我在之前很多文章里面,介绍过Winform主界面的开发,基本上都是标准的界面,在顶部放置工具栏,中间区域则放置多文档的内容,但是在顶部菜单比较多的时候,就需要把菜单分为几级处理,如可以在顶部菜单放置一 ...
- [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 ...
- JSP中列表展示,隔行变色以及S标签的使用
1.java代码 /** * 列表展示,隔行变色以及S标签的使用 * * @return */ public String list() { List<User> list = new A ...
- NgRx/Store 4 + Angular 5使用教程
这篇文章将会示范如何使用NgRx/Store 4和Angular5.@ngrx/store是基于RxJS的状态管理库,其灵感来源于Redux.在NgRx中,状态是由一个包含action和reducer ...
随机推荐
- UVA:11297-Census(二维线段树)
Census Time Limit: 8 sec Description This year, there have been many problems with population calcul ...
- 12,scrapy框架之post请求
今日概要 递归爬取解析多页页面数据 scrapy的post请求发送 1.递归爬取解析多页页面数据 - 需求:将糗事百科所有页码的作者和段子内容数据进行爬取切持久化存储 - 需求分析:每一个页面对应一个 ...
- opencv中的仿射变换
什么是仿射变换? 原理:1.一个任意的仿射变换都能表示为 乘以一个矩阵(线性变换) 接着再 加上一个向量(平移) 2.综上所述,我们能够用仿射变换来表示: 1)旋转(线性变换) 2)平移(向量加) 3 ...
- FreeMarker的基础语法使用 && 心得和技巧
FreeMarker语言 FreeMarker语言概述 FreeMarker是一个模板引擎,一个基于模板生成文本输出的通用工具,使用纯Java编写. FreeMarker被设计用来生成HTML Web ...
- 网络安全巧设置 Win2008 R2 防火墙详解(1)
针对一般中小企业型来说,如果希望对企业网络进行安全管理,不一定非得花高价钱购买专业的防火墙设置,直接借助操作系统本身自带的防火墙功能即可以满足一般企业的应用,今天我们就一起来探究一下Windows S ...
- 【Add Two Numbers】
题目: You are given two linked lists representing two non-negative numbers. The digits are stored in r ...
- 快速获取Android应用包名和Activity名
一.获取包名 方法1: 先说明一下这里讲的方法是通用的,而网上其他方法获取PackageName不通用(因为他是建立在root的基础上的,我不敢保证你的设备已经root). ①在android设备上点 ...
- JWT实现token的生成和认证demo
上篇写到对JWT的理解,这篇写一个小的demo来实践下 Github:https://github.com/wuhen152033/token/tree/dev 简介 本次的demo是基于Spring ...
- Python基础-week07 Socket网络编程
一 客户端/服务器架构 1.定义 又称为C/S架构,S 指的是Server(服务端软件),C指的是Client(客户端软件) 本章的中点就是教大写写一个c/s架构的软件,实现服务端软件和客户端软件基于 ...
- imx6移植librtmp
一.openssl交叉编译 1.下载 https://www.openssl.org/source/ 版本不要太高,刚开始版本高了,有些函数取消了,链接不上 使用1.0.1f即可 2.编译成共享库 . ...