• 技术文章 >web前端 >js教程

    Angular使用ngrx/store做状态管理

    青灯夜游青灯夜游2021-02-01 11:44:25转载594
    本篇文章给大家介绍一下Angular ngrx/store状态管理的使用。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。

    相关教程推荐:《angular教程

    Angular中使用ngrx做状态管理

    简介

    ngrx/store的灵感来源于Redux,是一款集成RxJS的Angular状态管理库,由Angular的布道者Rob Wormald开发。它和Redux的核心思想相同,但使用RxJS实现观察者模式。它遵循Redux核心原则,但专门为Angular而设计。

    Angular中的状态管理大部分可以被service接管,那么在一些中大型的项目中,这样做的弊端就会显露出来,其中之一就是状态流混乱,不利于后期维护,后来便借鉴了redux的状态管理模式并配上rxjs流式编程的特点形成了@ngrx/store这么一个作用于Angular的状态管理工具.

    @NgRx/Store 状态管理的三个原则

    首先,@NgRx/Store 同样遵守 Redux 的三个基本原则:

    这个原则是整个单页应用的状态通过object tree(对象树)的形式存储在store 里面。
    这个定义十分抽象其实就是把所有需要共享的数据通过javascript 对象的形式存储下来

    state =
    {
        application:'angular app',
        shoppingList:['apple', 'pear']
    }

    这个 ngrx/store 核心之一就是用户不能直接修改状态内容。 举个例子,如果我们需要保存了登录页面状态,状态信息需要记录登录用户的名字。 当登录名字改变,我们不能直接修改状态保存的用户名字

    state={'username':'kat'},
    //用户重新登录别的账户为tom
    state.username = 'tom'  //在ngrx store 这个行为是绝对不允许的

    由于不能直接需改状态,ngrx/store 同时引入了一个叫做reducer(聚合器)的概念。通过reducer 来修改状态。

    function reducer(state = 'SHOW_ALL', action) {
        switch (action.type) {
          	case 'SET_VISIBILITY_FILTER':
            	return Object.assign({}, state  ,newObj);  
            default:
            	return state  
            }
    	}

    ngrx/store使用实例

    1.安装@ngrx/store

    yarn add @ngrx/store

    2. 创建 state, action, reducer

    state 状态:
    app\store\state.ts

    //下面是使用接口的情况, 更规范
    export interface TaskList {
      id: number;
      text: string;
      complete: boolean;
    }
    
    export const TASKSAll: TaskList[] = [
      {id: 1, text: 'Java Article 1', complete: false},
      {id: 2, text: 'Java Article 2', complete: false}
    ]
    
    export interface AppState {
      count: number;
      todos: TaskList;
      // 如果要管理多个状态,在这个接口中添加即可
    }
    
    //这个是不用接口的情况
    // export interface AppState {
    //     count: number;
    //     todos: any;
    //     // 如果要管理多个状态,在这个接口中添加即可
    //   }

    reducer
    app\store\reducer.ts

    // reducer.ts,一般需要将state,action,reducer进行文件拆分
    import { Action } from '@ngrx/store';
    
    export const INCREMENT = 'INCREMENT';
    export const DECREMENT = 'DECREMENT';
    export const RESET = 'RESET';
    
    const initialState = 0;
    // reducer定义了action被派发时state的具体改变方式
    export function counterReducer(state: number = initialState, action: Action) {
      switch (action.type) {
        case INCREMENT:
          return state + 1;
    
        case DECREMENT:
          return state - 1;
    
        case RESET:
          return 0;
    
        default:
          return state;
      }
    }

    actions

    如果需要把action 单独提取出来, 参考 后面的
    5 如果想把action分离出来如何处理?

    3. 注册store

    根模块:
    app/app.module.ts

    import { NgModule } from '@angular/core';
    import { StoreModule } from '@ngrx/store';
    // StoreModule: StoreModule是@ngrx/storeAPI中的一个模块,
    // 它被用来在应用模块中配置reducer。
    
    import {counterReducer} from './store/reducer';
    
    @NgModule({
      imports: [
      	StoreModule.forRoot({ count: counterReducer }), // 注册store
      ],
    })
    export class AppModule {}

    4. 使用store

    在组件或服务中注入store进行使用

    以 app\module\article\article.component.ts 组件为例:

    // 组件级别
    import { Component } from '@angular/core';
    import { Store, select } from '@ngrx/store';
    import { Observable } from 'rxjs';
    import { INCREMENT, DECREMENT, RESET} from '../../store/reducer';
    
    interface AppState {
      count: number;
    }
    
    @Component({
      selector: 'app-article',
      templateUrl: './article.component.html',
      styleUrls: ['./article.component.css']
    })
    export class ArticleComponent  {
      count: Observable<number>;
    
      constructor(private store: Store<AppState>) { // 注入store
        this.count = store.pipe(select('count')); 
        // 从app.module.ts中获取count状态流
      }
    
      increment() {
        this.store.dispatch({ type: INCREMENT });
      }
    
      decrement() {
        this.store.dispatch({ type: DECREMENT });
      }
    
      reset() {
        this.store.dispatch({ type: RESET });
      }
    }

    模板页面:
    app\module\article\article.component.html

    <div class="state-count">
    
        <button (click)="increment()">增加Increment</button>
        <div>Current Count: {{ count | async }}</div>
        <button (click)="decrement()">减少Decrement</button>
    
        <button (click)="reset()">Reset Counter</button>
    </div>

    这里使用了 管道符 async, 在子模块里直接使用快报错 , 如果在子模块要实现 数据的双向绑定也会报错,具体原因参照 课件说明的 问题: The pipe ‘async’ could not be found?

    如何做到在模板页面中不使用管道 来渲染页面 ?

    修改如下:

    count: Observable<number>;
    
    constructor(private store: Store<AppState>) { // 注入store
        var stream = store.pipe(select('count')); 
        // 从app.module.ts中获取count状态流
        stream.subscribe((res)=>{
              this.count = res;
          })
      }

    为了管理方便, 一般会把 type , state, actions,reducers 分开来管理

    5 如果想把action分离出来如何处理?

    1. 新建 \app\store\actions.ts 文件
    import { Injectable } from '@angular/core';
    import { INCREMENT, DECREMENT, RESET } from './types';
    
    @Injectable()
    export class CounterAction{
        // Add=function(){}
        Add(){
            return { type: INCREMENT }
        }
    }
    
    // 就只这样导出是不行的
    // export function Add1(){
    //     return { type: INCREMENT }
    // }
    1. 在根模块 app.module.ts 注册
    import {CounterAction} from './store/actions';
    
    ... 
    
    providers: [CounterAction],
    1. 在组件中使用 – article.component.ts
    import {CounterAction} from '../../store/actions';
    
    export class ArticleComponent implements OnInit {
    
      constructor(
        private action: CounterAction  //注入CounterAction
        ) { }
    
        increment() {
        // this.store.dispatch({ type: INCREMENT }); 
        //把 actions分离出去
        this.store.dispatch(this.action.Add()); 
        
      }
    }

    更多编程相关知识,请访问:编程学习!!

    以上就是Angular使用ngrx/store做状态管理的详细内容,更多请关注php中文网其它相关文章!

    声明:本文转载于:csdn,如有侵犯,请联系admin@php.cn删除
    上一篇:浅谈Nodejs获取参数的几种方法 下一篇:jquery给元素设置/取消readonly和disabled属性
    大前端线上培训班

    相关文章推荐

    • Angular实现只执行正在开发的新单元测试• 分享Angular中关于表单的一些知识点• Angularjs自定义一个可输入的下拉框组件(代码示例)• 12个关于Angular的经典面试题

    全部评论我要评论

  • 取消发布评论发送
  • 1/1

    PHP中文网