前言: 最近在折腾一个 ionic4 项目,主要是围绕着 Angular 转圈圈,状态管理这块,Angular 官方的 @ngrx/store 用起来样板代码太多,索性换到了 mobx (react党😂),记录下折腾日记
代码已放到 github 上面
https://github.com/caoxiemeihao/mobx5-angular8
-
现在要完成一个简单的功能:
定义个跟组局,根组件的状态修改要反应到其他两个子组件中
screenshot1.png
- 实现思路:
Angular 的内部大量用到 Rxjs,如果把 mobx 中 @observable 的改变转换成为 Rxjs 的 Observable 是不是把 mobx 和 Angular 结合起来了呢?
核心代码
// src/store/mobx-rxjs.ts
import { computed } from 'mobx';
import { Observable, Subscriber } from 'rxjs';
/**
* mobx 与 rxjs 之间的桥梁
* @param expression 例如: () => this.store.xxxx
*/
export function fromMobx<T>(cb: () => any) {
return new Observable((subscriber: Subscriber<T>) => {
const _computed = computed(cb);
const disposer = _computed.observe(changed => {
subscriber.next(changed.newValue as T);
});
return () => {
if (disposer) disposer();
}
});
}
新建一个 store 项目中可以有n个 store
// src/store/app-store.ts
import { Injectable } from '@angular/core';
import { observable, action, reaction } from 'mobx';
@Injectable({
providedIn: 'root'
})
export class AppStore {
constructor() {
reaction(
() => ({
// 跟踪数据变动
red: this.counterRed,
green: this.counterGreen,
blue: this.counterBlue
}),
({ red, green, blue }) => {
// 计算总惦记次数
this.counter = red + green + blue;
}
);
}
@observable counter: number = 0;
@observable counterRed: number = 0;
@observable counterBlue: number = 0;
@observable counterGreen: number = 0;
@action.bound setCounter(color: 'red' | 'green' | 'blue') {
if (color === 'red') {
this.counterRed += 1;
} else if (color === 'green') {
this.counterGreen += 1;
} else if (color === 'blue') {
this.counterBlue += 1;
}
}
}
在组件中使用 将mobx转换成rxjs
// src/componets/counter/counter.ts
import { Component, DoCheck, ChangeDetectionStrategy } from "@angular/core";
import { Observable } from 'rxjs';
import { AppStore } from '@src/store/app-store';
import { fromMobx } from '@src/store/mobx-rxjs';
import { startWith } from 'rxjs/operators';
@Component({
selector: 'app-counter',
templateUrl: './counter.html',
styleUrls: ['./counter.less'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class CounterComponent implements DoCheck {
couter$: Observable<number>;
counter = 0;
constructor(
private store: AppStore
) {
this.couter$ = fromMobx<number>(() => this.store.counter).pipe(startWith(0));
this.counter = this.store.counter;
}
ngDoCheck() {
console.log('[this.store.counter]', this.store.counter)
}
}
模板代码
// src/components/counter/counter.html
<h2 class="alert alert-secondary rounded-0">
Counter组件
</h2>
<h3>
总点击次数 - Observable
<span class="badge badge-dark">{{couter$ | async}}</span>
</h3>
<h3>
总点击次数 - 原始类型
<span class="badge badge-dark">{{couter || 0}}</span>
</h3>
上面只写了部分代码,源码可以去gtihub上面拉下来自己跑下 😊
感受下 Rxjs 的魔性
网友评论