2

基于前两篇文章的铺垫,这一篇文章就很轻松了。

不同框架下使用xstate

官方为 vuereact 都提供了对应版本的 xstate ,具体细节可以参看:

angular 没有官方版本,具体使用可以参考 在Angular中使用xstate

使用原理

不管使用哪个框架,思路都大同小异:在状态机启动之后,监听 state 的改变,获取实时的 context (上下文),然后映射到页面中。

angular 中,xstate 被当作服务引用,状态机在启动之后,我们通过 rxjs状态转变转化成 observable对象,通过订阅去获取实时的 context (上下文)。

// 启动状态机
private machineSrv = interpret(covidMachine, { devTools: true }).start();

// 将状态机的变化转变成 observable
state$: Observable<any> = from(this.machineSrv).pipe(
  filter(state => state.changed)
);

总结:

  • 启动状态机
  • 监听状态机变化

组件联动

具体到某个组件想要使用状态机,则在组件相对应的生命钩子中引入启动后的状态机,获取 context

// app.component.ts
export class AppComponent {
  countryData: any[];
  countryList: any[];
  state: any = {};
  constructor(private covidSrc: CovidService) {
    // 订阅状态机服务,获取上下文,然后赋值
    this.covidSrc.state$.subscribe((covidState: any) => {
      this.state = covidState;
      const { countryRef, listCountries } = covidState.context;
      this.countryList = listCountries ? listCountries : [];
      this.countryData = countryRef
        ? this.processData(countryRef.state.context)
        : [];
    });
  }
  /** Helper */
  processData(data: any) {
    // 数据处理
  }
}

赋值之后,把值映射到 html 中即可。

<p style="text-align:center" *ngIf="state.context">
    {{ state.matches("idle") ? "Select a country" : null }}
</p>

<!-- 下拉框 -->
<app-select [data]="countryList" (selectChange)="selectCountry($event)"></app-select>

<!-- 数字卡片 -->
<app-number [data]="countryData"></app-number>

<!-- 条形图 -->
<app-bar [data]="countryData"></app-bar>

总结

我们拿到状态机,一般有两个作用:

  • 拿到状态,用 state.match 匹配状态

    <!-- 如果状态机处于“idle”状态时的处理 -->
    {{ state.matches("idle") ? "Select a country" : null }}
  • 拿到上下文(context),获取页面中需要的数据

    this.state = covidState;
    const { countryRef, listCountries } = covidState.context;
    this.countryList = listCountries ? listCountries : [];

至此,一个基于xstae的新冠动态追踪网页就搭建完成了,具体的细节打击可以参考线上Demo

往期回顾:


中原大虾
123 声望3 粉丝