你们觉得前端的“状态”和“状态管理”指的是什么?

2020-07-05 11:10:52 +08:00
 marcosteam

最近在写一个网站的新前端,需要用到大量数据之间的交互,记得这个是要用到状态管理的,然后去看了 Vuex 和 Redux,网站里面都在讲 State,Store,翻了一下知乎还有 V2EX 看看为什么需要状态管理,回答一般都是“跨组件管理状态”,这个回答真的很云里雾里,没有做到很好的解释什么是“状态”,什么是“状态管理”。那你们眼里的状态是什么?什么时候需要状态管理这个东西?

我个人的观点:状态管理统一管理就是各个组件之间公用的数据源,类似于一个数据库,组件需要什么数据要统一从状态管理库(比如 Vuex 和 Redux 中获取),同时状态管理还可以根据需求实时的更新 Store 里面的各种数据。而状态就是组件里私有的变量。

4404 次点击
所在节点    问与答
28 条回复
yixiang
2020-07-05 11:22:10 +08:00
状态这个概念并不是前端特有的…… 属于软件工程的基础概念? stackexchange 上有讨论: https://softwareengineering.stackexchange.com/questions/150120/definition-of-state

用前端举例的话,name => <div>{name}</div>,自己不保存数据,这个组件就是无状态的,相对,如果 <div>{this.state.name}</div>,保存了数据,那就是有状态的。

你说的情况是全局状态 vs 组件状态。

为啥会有这个需求,比如,显示当前已登录用户的用户名,很可能不同组件都需要显示这个数据,且需要随时更新。两种做法:

1. 在根组件比如 App 的 state 中保存,再一层一层 props 传下去
2. 想办法全局管理这个状态,再在组件中调用

显然 2 更方便。
marcosteam
2020-07-05 11:26:07 +08:00
@yixiang 其实还是把它提取成全局变量?
dcalsky
2020-07-05 11:31:11 +08:00
你想成树的数据结构好了。

状态:1. 每个叶子节点或非叶子节点带有的 State ; 2. 全局 State
状态管理:1.节点改变自己的 State ; 2. 节点改变自身 State 后要通知其他节点; 3. 节点改变全局 State
什么时候需要:1. 子节点有相互 State 依赖,并且树有一定高度; 2. 需要记录 /回溯每次 State 操作; 3. 全局 State 较多,且需要被子节点共享、操作、订阅(也就是并非只读的情况)。
Jirajine
2020-07-05 11:37:22 +08:00
felixcode
2020-07-05 11:42:52 +08:00
状态这个概念可能是从状态机出来的,软件设计和硬件设计都有应用,记录状态和控制状态变化是状态机的基本条件,程序运行可以看作是状态机的实现。
BearD01001
2020-07-05 12:02:20 +08:00
View = f(State)
Biwood
2020-07-05 12:17:29 +08:00
你的 append 里的理解没太大毛病,最重要的一点就是保证数据的单向流动,以避免庞大项目里面组件过多,对共享状态的随意更改可能会导致冲突和混乱
前端框架里所说的状态管理主要起源于 Facebook 提出的 Flux 架构,详细可以看官方说明 https://facebook.github.io/flux/docs/in-depth-overview
whisky221
2020-07-05 13:35:23 +08:00
最近就在做一个票券项目
对于 VueX 感觉很好用,但是目前项目上线了基本没有发现必须要用的场景
可以请教下通常什么场景下用状态管理会比较有好处呢?
otakustay
2020-07-05 13:58:08 +08:00
理论上,前端可以用一份或多份没有任何 DOM 和 BOM 特征的数据(普通的对象)来描述一个界面长什么样,这份数据叫做状态
而状态管理,就是如何管好这些状态,是一个领域,并不单单指全局的状态或者某一个具体的能力
状态管理是当前前端最核心的部分,因为视图能用状态描述,所以前端的逻辑复杂度移到了如何让状态“不要出错”。前端与后端的一个区别在于,状态在前端是长生命周期的,又会在这个生命周期中有不可枚举地、未知地、难以追踪的多次修改,通常来说保证每一次修改的正确性是不可能的
通常来说,状态管理要解决的问题很多,比如:
1. 我的状态怎么去更新(写法上的)
2. 我有多个组件要共享一个状态,如何共享
3. 我一开始不知道一个状态是要共享的,后来又要共享了,怎么提升这个状态
4. 一个原本共享的状态又随着时间不需要共享了,如何下降这个状态
5. 异步的竞争状态如何处理
6. 持久状态和临时状态如何区分维护
7. 状态更新的事务如何管理
还有非常非常多的话题,够前端再研究个三五年不是问题
azh7138m
2020-07-05 14:11:36 +08:00
@whisky221
> 可以请教下通常什么场景下用状态管理会比较有好处呢?

我认为任何时候都可以上状态管理,管理全部的状态,即极致的贫血模型。
当组件不再持有任何状态时,或者说组件完全受控时,也就是我们常说的纯函数组件,这个时候的组件是完全可测试的,一个确定的状态就会得到一个确定的界面,单测会非常的好写,UI 层也可以轻松达到 100% 的测试覆盖率。
我认为,更高的测试覆盖率,是对持续快速的软件开发很重要的一个事情。

状态管理除了可以更简单的在组件间共享部分状态外,我觉得更重要的一点是它带来的可测试性的提升。
在理想的场景下,在引入状态管理后,所有的组件都可以成为完全受控组件,副作用可以完全清理出组件,状态与 UI 的解耦会让测试变得简单容易。

当然,实际的场景下会有很多去不掉,或者说很难去掉的副作用,比如,动画。

一个具体的案例见 https://github.com/yuche/gouqi/issues/1
hyy1995
2020-07-05 14:11:41 +08:00
说白了就是全局变量,你附言里面表达的就是了
Hurriance
2020-07-05 14:13:06 +08:00
我也理解成全局变量,看文档的时候真的看的云里雾里
redbuck
2020-07-05 14:44:09 +08:00
界面就是数据(状态)的表达,它永远实时得展示数据。
状态管理就是中心化的操作数据。
界面不应修改数据,应该通知变更。reducer 或 mutation 都是对中心的通知,获得通知后如何做是中心的事情。数据操作完中心将变动后的数据下发,使界面更新(单向数据流)
theRealWhexy
2020-07-05 14:52:04 +08:00
个人理解

状态对应真值来源( source of truth )。
有时,不同的组件可能引用同一个 truth (例如:用户的昵称信息),并都可以对其进行修改。这时候就需要管理好 truth 的来源,保证系统中不会出现矛盾的信息。即尽可能保证“单一真值来源”( Single source of truth )。
保证单一真值来源的手段就是状态管理,各个系统里实现的手段多种多样,但都是为了信息的全局一致性服务的。
gouflv
2020-07-05 15:13:44 +08:00
不要被前端的 flux 这套东西带歪了,看看 angular 的方案
EPr2hh6LADQWqRVH
2020-07-05 15:29:29 +08:00
前端的状态管理源于不会写类和构造函数
marcosteam
2020-07-05 15:38:26 +08:00
@avastms 我第一次看函数化编程的时候也是云里雾里的,比如柯里化,明明一个函数就能解决的事情要两三个函数解决,之前学到的面向对象几乎都没怎么用过
otakustay
2020-07-05 15:55:46 +08:00
@marcosteam OO 不就是一个类能干的事要分成 3 个接口 6 个实现嘛,像 bridge 啊 builder 啊 strategy 啊
jingcoco
2020-07-05 18:52:35 +08:00
个人复述一下楼上的:简单应用不需要;方便测试;类似 redux 可以实现数据追踪,redo 等功能;类似 mobx 的感觉就是类似消息中间件;类似 rxjs 的感觉像之前后端的思路;基本都会跟你扯半天数据的 immutable,云里雾里的,感觉还是有难度的
ditel
2020-07-05 18:57:02 +08:00
状态管理=后台单独的数据服务器,关闭当前页相当于服务器重新初始化

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/687264

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX