最近在写一个网站的新前端,需要用到大量数据之间的交互,记得这个是要用到状态管理的,然后去看了 Vuex 和 Redux,网站里面都在讲 State,Store,翻了一下知乎还有 V2EX 看看为什么需要状态管理,回答一般都是“跨组件管理状态”,这个回答真的很云里雾里,没有做到很好的解释什么是“状态”,什么是“状态管理”。那你们眼里的状态是什么?什么时候需要状态管理这个东西?
我个人的观点:状态管理统一管理就是各个组件之间公用的数据源,类似于一个数据库,组件需要什么数据要统一从状态管理库(比如 Vuex 和 Redux 中获取),同时状态管理还可以根据需求实时的更新 Store 里面的各种数据。而状态就是组件里私有的变量。
1
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 更方便。 |
2
marcosteam OP @yixiang 其实还是把它提取成全局变量?
|
3
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 较多,且需要被子节点共享、操作、订阅(也就是并非只读的情况)。 |
4
Jirajine 2020-07-05 11:37:22 +08:00 via Android
|
5
felixcode 2020-07-05 11:42:52 +08:00
状态这个概念可能是从状态机出来的,软件设计和硬件设计都有应用,记录状态和控制状态变化是状态机的基本条件,程序运行可以看作是状态机的实现。
|
6
BearD01001 2020-07-05 12:02:20 +08:00 via iPhone
View = f(State)
|
7
Biwood 2020-07-05 12:17:29 +08:00
你的 append 里的理解没太大毛病,最重要的一点就是保证数据的单向流动,以避免庞大项目里面组件过多,对共享状态的随意更改可能会导致冲突和混乱
前端框架里所说的状态管理主要起源于 Facebook 提出的 Flux 架构,详细可以看官方说明 https://facebook.github.io/flux/docs/in-depth-overview |
8
whisky221 2020-07-05 13:35:23 +08:00
最近就在做一个票券项目
对于 VueX 感觉很好用,但是目前项目上线了基本没有发现必须要用的场景 可以请教下通常什么场景下用状态管理会比较有好处呢? |
9
otakustay 2020-07-05 13:58:08 +08:00 3
理论上,前端可以用一份或多份没有任何 DOM 和 BOM 特征的数据(普通的对象)来描述一个界面长什么样,这份数据叫做状态
而状态管理,就是如何管好这些状态,是一个领域,并不单单指全局的状态或者某一个具体的能力 状态管理是当前前端最核心的部分,因为视图能用状态描述,所以前端的逻辑复杂度移到了如何让状态“不要出错”。前端与后端的一个区别在于,状态在前端是长生命周期的,又会在这个生命周期中有不可枚举地、未知地、难以追踪的多次修改,通常来说保证每一次修改的正确性是不可能的 通常来说,状态管理要解决的问题很多,比如: 1. 我的状态怎么去更新(写法上的) 2. 我有多个组件要共享一个状态,如何共享 3. 我一开始不知道一个状态是要共享的,后来又要共享了,怎么提升这个状态 4. 一个原本共享的状态又随着时间不需要共享了,如何下降这个状态 5. 异步的竞争状态如何处理 6. 持久状态和临时状态如何区分维护 7. 状态更新的事务如何管理 还有非常非常多的话题,够前端再研究个三五年不是问题 |
10
azh7138m 2020-07-05 14:11:36 +08:00 2
@whisky221
> 可以请教下通常什么场景下用状态管理会比较有好处呢? 我认为任何时候都可以上状态管理,管理全部的状态,即极致的贫血模型。 当组件不再持有任何状态时,或者说组件完全受控时,也就是我们常说的纯函数组件,这个时候的组件是完全可测试的,一个确定的状态就会得到一个确定的界面,单测会非常的好写,UI 层也可以轻松达到 100% 的测试覆盖率。 我认为,更高的测试覆盖率,是对持续快速的软件开发很重要的一个事情。 状态管理除了可以更简单的在组件间共享部分状态外,我觉得更重要的一点是它带来的可测试性的提升。 在理想的场景下,在引入状态管理后,所有的组件都可以成为完全受控组件,副作用可以完全清理出组件,状态与 UI 的解耦会让测试变得简单容易。 当然,实际的场景下会有很多去不掉,或者说很难去掉的副作用,比如,动画。 一个具体的案例见 https://github.com/yuche/gouqi/issues/1 |
11
hyy1995 2020-07-05 14:11:41 +08:00
说白了就是全局变量,你附言里面表达的就是了
|
12
Hurriance 2020-07-05 14:13:06 +08:00 via iPhone
我也理解成全局变量,看文档的时候真的看的云里雾里
|
13
redbuck 2020-07-05 14:44:09 +08:00
界面就是数据(状态)的表达,它永远实时得展示数据。
状态管理就是中心化的操作数据。 界面不应修改数据,应该通知变更。reducer 或 mutation 都是对中心的通知,获得通知后如何做是中心的事情。数据操作完中心将变动后的数据下发,使界面更新(单向数据流) |
14
theRealWhexy 2020-07-05 14:52:04 +08:00
个人理解
状态对应真值来源( source of truth )。 有时,不同的组件可能引用同一个 truth (例如:用户的昵称信息),并都可以对其进行修改。这时候就需要管理好 truth 的来源,保证系统中不会出现矛盾的信息。即尽可能保证“单一真值来源”( Single source of truth )。 保证单一真值来源的手段就是状态管理,各个系统里实现的手段多种多样,但都是为了信息的全局一致性服务的。 |
15
gouflv 2020-07-05 15:13:44 +08:00 via iPhone
不要被前端的 flux 这套东西带歪了,看看 angular 的方案
|
16
EPr2hh6LADQWqRVH 2020-07-05 15:29:29 +08:00
前端的状态管理源于不会写类和构造函数
|
17
marcosteam OP @avastms 我第一次看函数化编程的时候也是云里雾里的,比如柯里化,明明一个函数就能解决的事情要两三个函数解决,之前学到的面向对象几乎都没怎么用过
|
18
otakustay 2020-07-05 15:55:46 +08:00
@marcosteam OO 不就是一个类能干的事要分成 3 个接口 6 个实现嘛,像 bridge 啊 builder 啊 strategy 啊
|
19
jingcoco 2020-07-05 18:52:35 +08:00 via iPhone
个人复述一下楼上的:简单应用不需要;方便测试;类似 redux 可以实现数据追踪,redo 等功能;类似 mobx 的感觉就是类似消息中间件;类似 rxjs 的感觉像之前后端的思路;基本都会跟你扯半天数据的 immutable,云里雾里的,感觉还是有难度的
|
20
ditel 2020-07-05 18:57:02 +08:00 via Android
状态管理=后台单独的数据服务器,关闭当前页相当于服务器重新初始化
|
21
jsun 2020-07-05 21:01:47 +08:00
就是一个全局变量或者说叫单例模式,然后搞了很多更新全局变量的方法,起了很多名词,弄得很乱
|
22
anguiao 2020-07-05 21:09:38 +08:00 via Android
状态就是全局变量,状态管理就是让你更方便、安全地使用这些全局变量。
这就是我现在粗浅的理解了,其他的技术名词我也说不上来。 |
23
Mutoo 2020-07-05 21:12:57 +08:00 1
Redux 、Vuex 这类状态管理的主要思想为 Single source of truth 意为“单一信任源”(@theRealWhexy 不是什么“真值来源”)。统一管理数据,有利于数据的完整性和一致性。
另外通过 FLUX-like 的单向数据流模型,确保数据只能从 Store 流向组件,并且 Store 只能被 Action 修改。这样组件职责更加单一,更容易维护。 |
24
janus77 2020-07-05 21:14:46 +08:00 via iPhone
状态就是全局变量。
状态管理,就是需要一套专门的东西来做了,这个全局变量只是一个最简单条件下的解决方案,随着场景的复杂需要更好的方案,这些方案的研究和发展就叫做状态管理 |
25
EminemW 2020-07-05 21:38:08 +08:00 1
全局变量,使用状态管理可以在变量数据发生改变时,通知使用该变量的组件重新渲染?
|
26
theRealWhexy 2020-07-06 00:11:02 +08:00 via iPhone
@Mutoo single source of truth 的翻译我还是斟酌了很久的,你这个我也不太满意。
|
27
Mutoo 2020-07-06 08:19:49 +08:00
@theRealWhexy (数据的)单一可信源,或者直接意译为单一数据源也可以。
|
28
no1xsyzy 2020-07-06 14:02:14 +08:00
状态就是任何可变的部分( moving parts )或其任何的组合。该词有可能启发自图灵机或者 FSM (状态转移)
状态管理就是通过单独的模块来管理(几乎)一切状态,包括但不限于 CRUD 。一个明显的好处是渲染方式和状态逻辑的正交化。换句话说,通过状态管理,你可以多处引用同一状态进行各种操作而不必考虑并发读写之类的问题。结果之一就是这些状态看上去 “全局” 了,但严格地说,是把 CRUD API 同时传到所有组件身上。 至于说 “几乎”,是因为确实有些状态没必要甚至不适合全局管理,尤其是随时可能以任何形式被复用的组件内部状态。 |