简单的安装 @ngxs/schematics

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

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

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>

事件触发其他事件

// 代码片段

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>
05-08 15:19