为什么要使用状态管理

我们平时开发的大部分项目,由于复杂度不够, 很少使用 Vuex、Redux 等状态管理库,就算引入了 Vuex 这些库,也只是当作一个全局数据引用,并非对应用状态进行管理。

但一旦页面的复杂度比较高,必然要引入状态管理,今天就聊聊我理解中的状态管理。

如果涉及到举例,由于我对Vuex更熟悉,团队内也大多比较熟悉Vue,因此会使用Vuex作例子。

到底什么时候应该使用状态管理

举例几个需要用 Vuex 的例子:

例子一

1
2
3
4
5
// Page.vue
<page>
<component-a />
<component-b />
</page>
1
2
3
4
// ComponentA.vue
<div>
<component-a-child />
</div>

比如这个例子中,<component-a-child />想和<component-b />通信,使用事件传递来解决非常麻烦。

当然也可以使用 EventBus,加一个全局的 vue 实例解决,但用 EventBus 还需要去关心事件的绑定解绑,需要手动处理事件,当这类组件,就会变得非常麻烦。

最好的解决办法就是抽象出通用的组件状态,放到 state 里面,接着通过 action/mutation 改变通用状态,而需要这些状态的组件则自己调用(mapState/mapGetter),不需要去关注组件之间的关系。

例子二

1
2
3
4
5
6
7
// Page.vue
<page>
<topic-list
:list="list"
:activity="activity"
:user="user" />
</page>
1
2
3
4
5
6
7
// TopicList.vue
<div>
<topic-header :list="list" :activity="activity" :user="user" />
<template v-for="item in list">
<topic :list="list" :data="item" :activity="activity" :user="user" />
</template>
</divt

这个例子里:list="list" :activity="activity" :user="user"在被不断的传递,实际里面的组件可能只需要里面的一两个属性。

当然,例子里面的代码比较简单,也可以通过合理的组件设计来解决。

但一旦碰到这种某几个状态数据不断被其子组件以及后代组件使用的状况,可以考虑使用状态管理来解耦,可能使代码更加简洁。

状态管理解决了什么

  • 最主要是解耦,把组件与组件之间的复杂关系解耦为数据与数据的关系,组件仅作单纯的数据渲染,而且由于是单一数据源,整体上非常便于维护。

以前是:

现在是:

  • 由于单一数据源+数据不可变,带来了应用状态的快照,可以很方便的实现前进/后退以及历史记录管理。

  • 可测试性,可以分别针对视图和数据进行测试,而不是混淆在一起,导致测试难度极大。

状态管理带来的新问题

最主要是由于解决使得单个组件复杂度的提升,但相比整体复杂度的降低以及更高的可维护性,这点代价是完全值得。

好的业务组件设计

一个好的业务组件必然是逻辑清晰以及方便修改维护。

下面以 Vue 为例子进行进行概念上的简单说明。

一些涉及到的概念

  1. 数据驱动 UI
  2. 单向数据流
  3. 有限状态机

模板

模板应保证逻辑清晰,业务复杂的部分可拆分成独立的业务组件又或者通过 computed 组装数据关系。

不应该在模板写逻辑语句,仅使用简单的条件判断以及方法调用或表达式。

状态的设计(data、computed)

状态分全局状态以及本地状态,全局状态就是 sotre(Vuex 或者自己另外定义的 Vue 对象),本地状态包括数据(data)以及根据数据响应的状态(computed)。

需要根据 data、store 或者 其他 computed 响应的同步状态都属于 computed,computed 必须是同步数据,computed 内部禁止任何异步操作。

所有需要异步获取以及无法由其他数据响应变化的数据都是 data。

有时候可以把 computed 作为一个不可写属性使用,返回一个常量或者其他想输入到模板的值。

原则是 data 的结构应清晰简单,数据之间的关系放在 computed。

数据的处理

服务器获取的数据不要在业务组件直接写请求,应通过 services 封装。

数据单位应保存一致(例如时间使用 13 位,金钱使用分),需要进行转换的数据按就近原则进行处理:如果是服务器数据在 services 进行转换,如果是用户输入的数据,通过 computed 进行 get/set 处理。

发送到服务器的数据也是一样,应在 services 里面处理数据的单位以及一些简单的判断。

保证代码的可维护性

  1. 代码、数据逻辑之间的关系应保持简单与一致,不应存在多种不同的业务关系模型。
  2. 单向数据流。
  3. 数据处理以及操作分开。
  4. 交互状态复杂的业务组件应用有限状态机以及 computed。
Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×