跳到主要内容

关于状态机的一些讨论

其实我们日常写代码中讨论最多的就是关于状态的问题,一个数据变变了,那么这个数据所代表的状态也需要改变。

维基百科上是这样解释的:

状态存储关于过去的信息,就是说:它反映从系统开始到现在时刻的输入变化。转移指示状态变更,并且用必须满足确使转移发生的条件来描述它。动作是在给定时刻要进行的活动的描述。有多种类型的动作:

进入动作(entry action):在进入状态时进行

退出动作(exit action):在退出状态时进行

输入动作:依赖于当前状态和输入条件进行

转移动作:在进行特定转移时进行

因为我是前端,就用前端的例子来表明,在我看来,react和vue这种前端的框架本质上也是一个状态机,规定了一系列内容:

  • 进入动作:数据初始化
  • 退出动作:数据清除、监听事件清除
  • 输入动作:数据(state)改变
  • 转移动作:diff后更新页面的内容

而这个状态变化是从小粒度去看(一个个的组件中)和从大粒度看(框架整体)来看是一致的,有一种统一的感觉,这样就导致了现在的前端开发更像搭积木,只要我们设计好了组件之间的数据关联,就可以自由的对这些模块进行组合然后达到自己想要的效果,这样一来增加了自由度,二来增加了丰富度,不过自由度的增加也导致了复杂度的上升,自由度本质上来说是约束,如果约束了只能这样写,那么我没的选,但是自由度越高就导致约束力不足,就会有很多的奇怪的组合,相比较而言,react中自由度更高一些,vue中的自由度就低一些,react的自由度几乎是javascript本身,但是vue就需要用到一些模版、指令等等一系列的东西。

接下来再来讨论下状态变化的问题,大家都知道,现在的前端框架几乎都是通过状态去改变页面的展示,那么为什么不去直接操作dom呢,那就是当状态频繁改变的时候,尤其是多个动作更改同一个dom的时候会让人的脑子无法准确的控制,并且不容易追踪,而且频繁的操作dom也会导致性能的下降,所以就前端就出现了state这样的一个说法,其实本质上就是一个中间层,把一部分的复杂度抽离到框架中,开发者就只需要关注状态的变化了。

然后状态的更新分两种,通过值的方式和通过信号的方式,众所周知,在react中是推崇函数式编程的,16.8之后逐渐抛弃了class的写法,转向函数式,函数式编程的一个重要概念就是避免可变对象,所以react中很多方案都是基于不可变对象来设计的,当你需要更新的时候就需要返回一致新的值而不是在旧值上进行修改,这种状态更新就属于通过值的方式。在vue中则相反,他通过proxy(vue3)劫持了状态数据,然后监听数据的变化更新页面的内容,如果开发者返回了一个新的对象,那么vue就会监听不到这个数据,导致无法更新。

除了状态的更新,react和vue还有一个区别就是控制粒度的区别,不过这个不属于状态机的范畴了,以后有时间再讨论。

Loading Comments...