第一个计数器案例: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:列表展示的更多相关文章

  1. ngrx/store effects 使用总结1:计数器

    本教程案例github:https://github.com/axel10/ngrx_demo-counter-and-list angular2+ 的学习成本应该是三大框架中最高的一个,教程及案例稀 ...

  2. [Angular2] @Ngrx/store and @Ngrx/effects learning note

    Just sharing the learning experience related to @ngrx/store and @ngrx/effects. In my personal opinio ...

  3. Angular应用架构设计-3:Ngrx Store

    这是有关Angular应用架构设计系列文章中的一篇,在这个系列当中,我会结合这近两年中对Angular.Ionic.甚至Vuejs等框架的使用经验,总结在应用设计和开发过程中遇到的问题.和总结的经验, ...

  4. Vuex 教程案例:计数器以及列表展示

    本案例github:https://github.com/axel10/Vuex_demo-Counter-and-list 本篇教程将以计数器及列表展示两个例子来讲解Vuex的简单用法. 从安装到启 ...

  5. Winform开发主界面菜单的动态树形列表展示

    我在之前很多文章里面,介绍过Winform主界面的开发,基本上都是标准的界面,在顶部放置工具栏,中间区域则放置多文档的内容,但是在顶部菜单比较多的时候,就需要把菜单分为几级处理,如可以在顶部菜单放置一 ...

  6. [Angular 2] ngrx/store

    @ngrx/store builds on the concepts made popular by Redux and supercharges it with the backing of RxJ ...

  7. [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 ...

  8. JSP中列表展示,隔行变色以及S标签的使用

    1.java代码 /** * 列表展示,隔行变色以及S标签的使用 * * @return */ public String list() { List<User> list = new A ...

  9. NgRx/Store 4 + Angular 5使用教程

    这篇文章将会示范如何使用NgRx/Store 4和Angular5.@ngrx/store是基于RxJS的状态管理库,其灵感来源于Redux.在NgRx中,状态是由一个包含action和reducer ...

随机推荐

  1. systick运用

    systick的原理前一篇博文有介绍,简而言之就是SysTick定时器是一个24位的倒计数,当倒计数为0时,将从RELOAD寄存器中取值作为定时器的初始值,同时可以选择在这个时候产生中断(异常号:15 ...

  2. Cyclic Nacklace HDU - 3746 (kmp)

    Cyclic Nacklace Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)T ...

  3. 【Isamaru, Hound of Honda】SVN常用命令补遗

    一些常用的 就是svn commit的时候 都必须是最新版本的东西 不能不是,但是其实只是.svn在控制,所以可以update到最新版本再svn merge -r 20:10 将版本10和20的融合, ...

  4. Android开发——用户在屏幕上的手势识别

    个定点决定.四个属性分别为left(1),top(2),right(3),bottom(4). 数字为图上标出的距离.显然这四个属性是相对于父容器来定的,均可以通过get()方法获取. 因此很容易得出 ...

  5. Codeforces 664D Graph Coloring 二分图染色

    题意: 一个无向图的每条边为红色或蓝色,有这样一种操作:每次选一个点,使与其相邻的所有边的颜色翻转. 求解是否可以经过一系列操作使所有的边颜色相同,并输出最少操作次数和相应的点. 分析: 每个点要么选 ...

  6. Java-数据结构之栈练习

    栈(stack)可以看做是特殊类型的线性表,访问.插入和删除其中的元素只能在栈尾(栈顶)进行. 队列(queue)表示一个等待的线性表,它也可以看做是一种特殊类型的线性表,元素只能从队列的末端(队列尾 ...

  7. Helloworld 在jvm 内存图

    HelloWorld.java源码如下:   public class HelloWorld { public static void main(String[] args) { String s ; ...

  8. Mybatis使用- Mybatis JdbcType与Oracle、MySql数据类型对应列表 ; Mybatis中javaType和jdbcType对应关系

    Mybatis JdbcType与Oracle.MySql数据类型对应列表  Mybatis JdbcType Oracle MySql JdbcType ARRAY     JdbcType BIG ...

  9. Spring boot 上传文件大小限制

    1.spring boot 1.x 版本 application.properties 文件中 位置在(resources下) spring.http.multipart.maxFileSize = ...

  10. BZOJ 1096: [ZJOI2007]仓库建设(DP+斜率优化)

    [ZJOI2007]仓库建设 Description L公司有N个工厂,由高到底分布在一座山上.如图所示,工厂1在山顶,工厂N在山脚.由于这座山处于高原内陆地区(干燥少雨),L公司一般把产品直接堆放在 ...