你们觉得前端的“状态”和“状态管理”指的是什么? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
marcosteam
V2EX    问与答

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

  •  2
    nbsp;
  •   marcosteam 2020-07-05 11:10:52 +08:00 4783 次点击
    这是一个创建于 1929 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

    第 1 条附言    2020-07-05 11:44:55 +08:00
    也许我能再讲的详细一点?

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

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

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

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

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

    状态对应真值来源( source of truth )。
    有时,不同的组件可能引用同一个 truth (例如:用户的昵称信息),并都可以对其进行修改。这时候就需要管理好 truth 的来源,保证系统中不会出现矛盾的信息。即尽可能保证“单一真值来源”( Single source of truth )。
    保证单一真值来源的手段就是状态管理,各个系统里实现的手段多种多样,但都是为了信息的全局一致性服务的。
    gouflv
        15
    gouflv  
       2020-07-05 15:13:44 +08:00 via iPhone
    不要被前端的 flux 这套东西带歪了,看看 angular 的方案
    EPr2hh6LADQWqRVH
        16
    EPr2hh6LADQWqRVH  
       2020-07-05 15:29:29 +08:00
    前端的状态管理源于不会写类和构造函数
    marcosteam
        17
    marcosteam  
    OP
       2020-07-05 15:38:26 +08:00
    @avastms 我第一次看函数化编程的时候也是云里雾里的,比如柯里化,明明一个函数就能解决的事情要两三个函数解决,之前学到的面向对象几乎都没怎么用过
    otakustay
        18
    otakustay  
       2020-07-05 15:55:46 +08:00
    @marcosteam OO 不就是一个类能干的事要分成 3 个接口 6 个实现嘛,像 bridge 啊 builder 啊 strategy 啊
    jingcoco
        19
    jingcoco  
       2020-07-05 18:52:35 +08:00 via iPhone
    个人复述一下楼上的:简单应用不需要;方便测试;类似 redux 可以实现数据追踪,redo 等功能;类似 mobx 的感觉就是类似消息中间件;类似 rxjs 的感觉像之前后端的思路;基本都会跟你扯半天数据的 immutable,云里雾里的,感觉还是有难度的
    ditel
        20
    ditel  
       2020-07-05 18:57:02 +08:00 via Android
    状态管理=后台单独的数据服务器,关闭当前页相当于服务器重新初始化
    jsun
        21
    jsun  
       2020-07-05 21:01:47 +08:00
    就是一个全局变量或者说叫单例模式,然后搞了很多更新全局变量的方法,起了很多名词,弄得很乱
    anguiao
        22
    anguiao  
       2020-07-05 21:09:38 +08:00 via Android
    状态就是全局变量,状态管理就是让你更方便、安全地使用这些全局变量。
    这就是我现在粗浅的理解了,其他的技术名词我也说不上来。
    Mutoo
        23
    Mutoo  
       2020-07-05 21:12:57 +08:00   1
    Redux 、Vuex 这类状态管理的主要思想为 Single source of truth 意为“单一信任源”(@theRealWhexy 不是什么“真值来源”)。统一管理数据,有利于数据的完整性和一致性。

    另外通过 FLUX-like 的单向数据流模型,确保数据只能从 Store 流向组件,并且 Store 只能被 Action 修改。这样组件职责更加单一,更容易维护。
    rb6221
        24
    rb6221  
       2020-07-05 21:14:46 +08:00 via iPhone
    状态就是全局变量。
    状态管理,就是需要一套专门的东西来做了,这个全局变量只是一个最简单条件下的解决方案,随着场景的复杂需要更好的方案,这些方案的研究和发展就叫做状态管理
    EminemW
        25
    EminemW  
       2020-07-05 21:38:08 +08:00   1
    全局变量,使用状态管理可以在变量数据发生改变时,通知使用该变量的组件重新渲染?
    theRealWhexy
        26
    theRealWhexy  
       2020-07-06 00:11:02 +08:00 via iPhone
    @Mutoo single source of truth 的翻译我还是斟酌了很久的,你这个也不太满意。
    Mutoo
        27
    Mutoo  
       2020-07-06 08:19:49 +08:00
    @theRealWhexy (数据的)单一可信源,或者直接意译为单一数据源也可以。
    no1xsyzy
        28
    no1xsyzy  
       2020-07-06 14:02:14 +08:00
    状态就是任何可变的部分( moving parts )或其任何的组合。该词有可能启发自图灵机或者 FSM (状态转移)
    状态管理就是通过单独的模块来管理(几乎)一切状态,包括但不限于 CRUD 。一个明显的好处是渲染方式和状态逻辑的正交化。换句话说,通过状态管理,你可以多处引用同一状态进行各种操作而不必考虑并发读写之类的问题。结果之一就是这些状态看上去 “全局” 了,但严格地说,是把 CRUD API 同时传到所有组件身上。
    至于说 “几乎”,是因为确实有些状态没必要甚至不适合全局管理,尤其是随时可能以任何形式被复用的组件内部状态。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1175 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 23:40 PVG 07:40 LAX 16:40 JFK 19:40
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86