zoukankan      html  css  js  c++  java
  • ngxs 状态管理器

    简单的安装 @ngxs/schematics

    $ ng add @ngxs/schematics
    $ ng g ngxs-sk --spec  // 会生成一个 src/store 文件
    
    1. 配置 src/store 下的config文件 (完成todo)。
    2. 在Core模块中导入NgxsStoreModule模块,没有创建Core就直接在AppModule中导入。

    ng6,rxjs6.0.0,ngxs3.0.1

    λ ng new ngxs  --style=styl --routing --skip-install
    λ cd ngxs
    λ yarn
    λ yarn add @ngxs/store
    λ yarn add @ngxs/logger-plugin @ngxs/devtools-plugin --dev
    λ ng g c template1
    λ ng g c template2
    λ code .
    

    在app下创建 app=>ngxs[actions, models, state] 3个文件夹

    models

    // model.ts
    
     //  存储数据模型
    export interface Tutorial {
      name: string;
      url: string;
    }
    

    actions

    // action.ts
    
    import { Tutorial } from '../models/tutorial.model';
    
    export class AddTutorial {
    
      // 需要一个唯一的标识
      static readonly type = '[TUTORIAL] Add';
    
      // 函数接收的参数
      constructor(public payload: Tutorial) { }
    }
    
    export class RemoveTutorial {
      static readonly type = '[TUTORIAL] Remove';
    
      constructor(public payload: string) { }
    }
    

    state

    // state.ts
    
    import { State, Action, StateContext, Selector } from '@ngxs/store';
    
    // models
    import { Tutorial } from '../models/tutorial.model';
    
    // actions
    import { AddTutorial, RemoveTutorial } from '../actions/tutorial.actions';
    
    // state
    export class TutorialStateModel {
      tutorials: Array<Tutorial>;
    }
    
    @State<TutorialStateModel>({
      name: 'tutorials',
      defaults: {
        tutorials: []
      }
    })
    export class TutorialState {
      @Selector()
      static getTutorials(state: TutorialStateModel) {
        return state.tutorials;
      }
    
      // 接收一个事件模型
      @Action(AddTutorial)
      // add(stateContext, arguments)
      add({
        getState, patchState }: StateContext<TutorialStateModel>,
        { payload }: AddTutorial) {
        const state = getState();
        patchState({
          tutorials: [...state.tutorials, payload]
        });
      }
    
      // 接收一个事件模型
      @Action(RemoveTutorial)
      remove({
        getState, patchState }: StateContext<TutorialStateModel>,
        { payload }: RemoveTutorial) {
        patchState({
          tutorials: getState().tutorials.filter(a => a.name !== payload)
        });
      }
    }
    

    app.module.ts

    import { NgxsModule } from '@ngxs/store';
    import { TutorialState } from './ngxs/state/tutorial.state';
    import { NgxsReduxDevtoolsPluginModule } from '@ngxs/devtools-plugin';
    import { NgxsLoggerPluginModule } from '@ngxs/logger-plugin';
    
    @NgModule({
      imports: [
        NgxsModule.forRoot([
          TutorialState
        ]),
        NgxsReduxDevtoolsPluginModule.forRoot(),
        NgxsLoggerPluginModule.forRoot()
      ]
    })
    export class AppModule { }
    

    组件内使用数据

    import { Component, OnInit } from '@angular/core';
    
    import { Observable } from 'rxjs/observable';
    
    import { Store, Select } from '@ngxs/store';
    import { TutorialState } from '../ngxs/state/tutorial.state';
    import { Tutorial } from '../ngxs/models/tutorial.model';
    import { RemoveTutorial } from '../ngxs/actions/tutorial.actions';
    
    
    @Component({
      selector: 'app-template2',
      templateUrl: './template2.component.html',
      styleUrls: ['./template2.component.styl']
    })
    export class Template2Component implements OnInit {
    
      // tutorials$: Observable<Tutorial>;
    
      // Select 直接映射数据事件
      @Select(TutorialState.getTutorials) tutorials$: Observable<Tutorial>;
    
      constructor(private store: Store) {
        // this.tutorials$ = this.store.select(state => state.tutorials.tutorials);
      }
    
      delTutorial(name) {
        this.store.dispatch(new RemoveTutorial(name));
      }
    
      ngOnInit() { }
    }
    

    模板渲染

    <ul *ngIf="tutorials$">
        <li *ngFor="let item of tutorials$ | async">
          name: {{ item.name}}
          <br> url: {{ item.url }}
        </li>
    </ul>
    

    发出单个字符串

    // state.ts
    export class TitleModel {
      title: string;
    }
    
    @State<TitleModel>({
      name: 'title',
      defaults: {
        title: 'hello Ajanuw'
      }
    })
    export class TitleState {
      @Selector()
      static getTitle(state: TitleModel) {
        return state.title;
      }
    }
    
    // app.module.ts
    import { UsersState , TitleState} from './ngxs-store/state/users.state';
    NgxsModule.forRoot([UsersState, TitleState]),
    
    // component.ts
    import { User, Title } from '../ngxs-store/models/users.model';
    @Select(TitleState.getTitle) title$: string;
    
    // component.html
    <h2> {{ title$ | async }} </h2>
    

    事件触发其他事件

    使用状态上下文对象中包含dispatch的函数

    // 代码片段
    
    export class UserInfoState {
      @Selector()
      static userinfs(state: UserInfoModel) {
        return state.userinfos;
      }
      @Action(AddUserInfo)
      add(
        { getState, patchState, dispatch }: StateContext<UserInfoModel>,
        { userInfo }: AddUserInfo,
      ) {
        const state = getState();
        patchState({
          userinfos: [...state.userinfos, userInfo],
        });
        dispatch(new UserInfoCount()); // 这里
      }
    
      @Action(UserInfoCount)
      count({ getState }: StateContext<UserInfoModel>) {
        const state = getState();
        console.log(state.userinfos.length);
      }
    }
    

    异步事件

    // promise
    
    export class UserInfoState {
      @Action(AddUserInfo)
      async add(
        { getState, patchState }: StateContext<UserInfoModel>,
        { userInfo }: AddUserInfo,
      ) {
        const userinfo = await this.checkRepeatName(userInfo); // 硬编码2s后得到结果
        const state = getState();
        patchState({
          userinfos: [...state.userinfos, userinfo],
        });
      }
    
      // 添加用户信息时检查用户名是否已经存在,(具体实现不重要)
      private checkRepeatName(userInfo: UserInfo): Promise<UserInfo> {
        return new Promise(resolve => {
          setTimeout(() => {
            resolve(userInfo);
          }, 2000);
        });
      }
    }
    
    // Observable
    
    export class UserInfoState {
      @Selector()
      static userinfs(state: UserInfoModel) {
        return state.userinfos;
      }
      @Action(AddUserInfo)
      add(
        { getState, patchState }: StateContext<UserInfoModel>,
        { userInfo }: AddUserInfo,
      ) {
        return this.checkRepeatName(userInfo).pipe(
          tap((userinfo: UserInfo) => {
            const state = getState();
            patchState({
              userinfos: [...state.userinfos, userinfo],
            });
          }),
        );
      }
    
      // 添加用户信息时检查用户名是否已经存在,(具体实现不重要)
      private checkRepeatName(userInfo: UserInfo): Observable<UserInfo> {
        return of(userInfo).pipe(delay(2000));
      }
    }
    

    事件回掉

    import { Component, OnInit } from "@angular/core";
    
    import { Store, Select } from "@ngxs/store";
    import { UserInfoState, UserInfoModel } from "./shared/store/user.state";
    import { Observable } from "rxjs";
    import { UserInfo } from "./shared/store/user.model";
    import { AddUserInfo } from "./shared/store/user.action";
    import { FormBuilder, FormGroup, Validators } from "@angular/forms";
    
    const l = console.log;
    @Component({
      selector: "app-root",
      templateUrl: "./app.component.html",
      styleUrls: ["./app.component.styl"],
    })
    export class AppComponent implements OnInit {
      @Select(UserInfoState.userinfs)
      public userinfos$: Observable<UserInfo>;
    
      public userinfoFrom: FormGroup = this.fb.group({
        name: [
          "",
          {
            validators: [Validators.required],
          },
        ],
        age: [
          "",
          {
            validators: [
              Validators.required,
              Validators.max(100),
              Validators.min(18),
            ],
          },
        ],
      });
      public get name() {
        return this.userinfoFrom.get("name");
      }
      constructor(private store: Store, private fb: FormBuilder) {}
    
      ngOnInit(): void {}
    
      public addUserInfo(e: HTMLFormElement): void {
        const userinfo: UserInfo = this.userinfoFrom.value;
        this.store
          .dispatch(new AddUserInfo(userinfo))
          .subscribe((v: UserInfoModel) => { // 这里
            e.reset();
          });
      }
    }
    
    <div>
      <form
        action=""
        [formGroup]="userinfoFrom"
        (ngSubmit)="addUserInfo(form)"
        #form
      >
        <div>
          <input type="text" placeholder="name" formControlName="name" /><span
            *ngIf="
              name.invalid && (name.dirty || name.touched) && !!name.errors.required
            "
            >name必填</span
          >
        </div>
        <div><input type="number" placeholder="age" formControlName="age" /></div>
        <div>
          <button type="submit" [disabled]="!userinfoFrom.valid">Submit</button>
        </div>
      </form>
    </div>
    <ul>
      <li *ngFor="let el of (userinfos$ | async)">{{ el.name }} - {{ el.age }}</li>
    </ul>
    
  • 相关阅读:
    ActiveMQ介绍及安装
    Spring注解驱动开发
    Redis 安装、配置、集群
    FastDFS的使用
    How are you vs How are you doing
    阅微草堂笔记
    我在实习的英文表达
    INTRO: THE DAWN (亡灵序曲) 中独白
    银魂的武士道
    Linguistic Data Consortium (LDC)
  • 原文地址:https://www.cnblogs.com/ajanuw/p/8993224.html
Copyright © 2011-2022 走看看