关于 Vue 的状态管理的一点困惑 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
shintendo
V2EX    Vue.js

关于 Vue 的状态管理的一点困惑

  •  
  •   shintendo 2022-09-15 18:10:57 +08:00 4245 次点击
    这是一个创建于 1122 天前的主题,其中的信息可能已经有所发展或是发生变。

    背景:Vue 版本 2.7 ,2 到 3 人的小项目,不使用 composition api ,不使用 SSR

    目的:只是想要响应式的全局变量

    关于 Vuex ,一个常见的说法是"大项目更需要,小项目不必强行用",我的问题是:

    1.Pinia 仍然适用这个说法吗?还是说 Pinia 因为更简单所以无脑上?

    2.如果嫌嗦不想用 Vuex 的话,可以用什么?很多地方包括 Vue 2 的文档提到 Event Bus 模式,但我也看到很多博客和论坛包括 Vue 的 Core Team 开发者都强烈反对这一模式。其中一个原因是说,Event Bus 没有一个中心化的 state ,而是用事件的发布 /订阅来同步数据,因此难以维护。

    问题来了,Event Bus 为什么不用中心化的 state ?或者说,为什么不是 Data Bus 而是 Event Bus ?我的意思是:

    // bus.js const bus = new Vue({ data () { count: 1 } }) Vue.prototype.$bus = bus // App.vue <template> <div> {{ $bus.count }} <button @click="$bus.count++">Add</button> </div> </template> 

    这样写我试了一下是可以的,数据也是响应式的,我觉得似乎是一个很自然的想法?但是为什么搜不到任何相关的讨论,甚至不知道这个模式有没有名字(类似 Event Bus )?还是说有什么我没看到的原因导致不能这样写?

    问的有点乱,简单说就是用一个 Vue 实例来充当 Store 是不是反模式?

    26 条回复    2022-09-16 19:57:07 +08:00
    thinkershare
        1
    thinkershare  
       2022-09-15 18:21:29 +08:00   1
    Vue 实例对象不是用来干这件事的, 另外响应式对象的确可用达到你的目的
    使用 Vuex 是因为它有其它用途, 需要一个全局的状态管理器, 而且这个状态管理器需要可观察性(这一点非常重要, 也是它为什么设计的如此难用的重要原因).
    Pinia 基本可用无脑上.
    EventBus 在前端不合适的原因你已经说了, 因为它需要数据同步.
    throns
        2
    throns  
       2022-09-15 18:23:29 +08:00 via iPhone
    你甚至可以把你的状态保存到 window 对象来存入,还有很多别的方式莱实现状态共享。为什么要有专门做状态管理的库呢?
    sunwang
        3
    sunwang  
       2022-09-15 18:25:12 +08:00   1
    我的理解是区别不大,如果使用 Event Bus 的话是没有一个专门的文件去维护全局状态的,全部操作都要放到监听函数里。如果使用 Vuex 的话,是会有一个专门的文件去管理,理论上是更清晰的。从实现上其实没区别,Vuex 内部也会实例化一个 vm 用来做响应式,个人拙见。
    sechi
        4
    sechi  
       2022-09-15 18:26:20 +08:00   1
    可以但没必要,这写法太不规范了。现在你们两三个人写项目还比较好沟通,如果以后加人呢?如果以后换人维护呢?接手项目的人估计第一反应是先骂一句。用了 pinia 起码人家稳定维护,还有完整的文档,况且它的体量又不大,何乐而不为呢?
    gouflv
        5
    gouflv  
       2022-09-15 18:38:38 +08:00 via iPhone   1
    vue 文档里不是说了简单 store 的模式吗,只是大部分人忽略了而已
    wu67
        6
    wu67  
       2022-09-15 18:42:53 +08:00
    别听那些文章瞎说, 有状态共享的需求, 就直接上. 除非你确定你的项目写完就扔, 不再维护, 不然迟早会出现第二个、第三个要共享的状态数据, 那为什么不用 vuex
    KouShuiYu
        7
    KouShuiYu  
       2022-09-15 18:56:11 +08:00   1
    你问的在官方文档里都有
    https://v2.cn.vuejs.org/v2/guide/state-management.html


    既然用 Vue 2.7 响应式的全局变量推荐的方式是这种, 比 Pinia 简单多了
    ```
    import { ref } from "vue";

    export const count = ref(1);
    export const countAdd = () => count.value++;
    ```

    那么 什么时候用 Pinia 呢?
    需要用到后端 SSR 时,原因: https://pinia.vuejs.org/introduction.html#why-should-i-use-pinia
    fool079
        8
    fool079  
       2022-09-15 19:14:52 +08:00
    其实你这么写已经是一个简单的 vuex 了~
    zcf0508
        9
    zcf0508  
       2022-09-15 19:16:17 +08:00 via Android
    在用 hami-vuex ,api 比较友好
    Q4h7388nR28s95fa
        10
    Q4h7388nR28s95fa  
       2022-09-15 19:21:10 +08:00
    Vue 文档有简单 store 的模式,小型项目使用这个模式没什么问题,我基本就是用这个。很多项目其实用不到 Vuex 。
    Vegetable
        11
    Vegetable  
       2022-09-15 19:24:40 +08:00
    这不是和 const bus = reactive({count:1}) 一样吗
    toesbieya
        12
    toesbieya  
       2022-09-15 20:47:12 +08:00
    vuex 太垃圾了,语法提示 P 都没有,取个值都罗里吧嗦,直接 reactive 一把梭
    w88975
        13
    w88975  
       2022-09-15 20:55:40 +08:00
    用了下 pinia ,感觉没有 mobx 那套用起顺手,于是用 reactive 自己撸了
    linkopeneyes
        14
    linkopeneyes  
       2022-09-15 23:09:49 +08:00   1
    实在烦就用 reactive 从顶部注入一下就好了最简单了
    wakarimasen
        15
    wakarimasen  
       2022-09-15 23:23:11 +08:00 via Android
    其实流行的库和框架就相当于“制式武器”的东西。
    shakukansp
        16
    shakukansp  
       2022-09-16 01:17:07 +08:00   1
    vuex 里存的东西很少,都是全局要用的用户信息、全局视图状态啥的
    别的页面都是局部的业务状态共享

    项目还用 vuex 存全部的业务状态,说明你这项目页面还不够多,业务类型还不够多
    YuTengjing
        17
    YuTengjing  
       2022-09-16 02:40:27 +08:00   1
    1. pinia 适用,状态管理工具本质上大同小异
    2. 不想要用可以,那你应该没法像 pinia 那样使用 vue devtools 集成,简单的场景可以用状态提升或者 provide/inject ,vue3 直接导出一个 ref 就可以了
    3. 本质上状态管理工具和你自己写的这个例子一样底层都是使用发布订阅,只不过功能更丰富,更好维护。背后的生态才是更重要的,比如你想做 state 持久化,vuex 可以直接用 https://github.com/robinvdvleuten/vuex-persistedstate 。那这时候你要做持久化,如果之前没用第三方框架自己手撸持久化吗?
    4. 如果这可以满足你的需求直接就这样用就完事了,你觉得很自然?我觉得一点都不自然。你写的代码有哪里可以看出官方是想让你这么用的,Vue 构造器是来用来构建 VM 实例的。如果要看着像是用来构造响应式数据的为什么不直接叫 Reactive 而要叫 Vue 。只不过它在这里刚好能实现你想要的响应式的数据罢了。
    yaphets666
        18
    yaphets666  
       2022-09-16 09:42:48 +08:00
    一个常见的说法是"大项目更需要,小项目不必强行用"

    这谁说的? vue 要的就是简单,谁都能看懂,所以工具就要统一,就用 vuex
    yaphets666
        19
    yaphets666  
       2022-09-16 09:44:28 +08:00
    写什么东西要有什么东西的思维,要入乡随俗,别拿锄头吃饭,也别拿筷子去犁地。反面例子就是早期版本的 AntDesign-Vue
    Terry05
        20
    Terry05  
       2022-09-16 09:49:10 +08:00   1
    在 vue3 的官方文档里,对于状态管理的部分,开篇就介绍了可以使用 reactive 来创建一个简易的响应式状态对象

    // /store/index.js
    export cosnt store = reactive({ count: 0 })

    // 任意位置
    import { store } from '@/store'
    console.log(store.count)

    使用 reactive 来作为组件级别的状态管理非常好用,我自己在 2.7 和 3.x 上多了它以后,对于 vuex / pinia 的使用就大幅减少,而是以功能模块为单位,使用 reactive 的方式来管理、维护和应用模块内的状态,只是全局的状态,比如用户、权限、模块、当前各种系统状态这类系统级的状态还是应该由 vuex / pinia 来管理比较合适

    当然,在使用了 reactive 后,provide / inject 就几乎没再使用过了
    tomieric
        21
    tomieric  
       2022-09-16 10:42:52 +08:00   1
    vue2 还有 observale ,经常有小型的 vuex 效果,在 SFC 中用 computed 获取 state

    ```js
    export default function(cOnfig= {}) {
    const store = {
    state: {
    ...config
    },
    actions: { },
    mutations: {
    validate (state, { row, prop, validate, messages }) {
    },
    },
    commit: (key, value) => {
    if (store.mutations[key]) {
    store.mutations[key](store.state, value);
    } else {
    throw new Error(`mutations: ${key} 未定义`);
    }
    },
    dispatch: async (key, value) => {
    if (store.actions[key]) {
    const result = await store.actions[key](
    {
    state: store.state,
    commit: store.commit,
    dispatch: store.dispatch
    },
    value
    );
    return Promise.resolve(result);
    } else {
    throw new Error(`actions: ${key} 未定义`);
    }
    }
    };

    return Vue.observable(store);
    }

    ```
    shintendo
        22
    shintendo  
    OP
       2022-09-16 11:17:03 +08:00
    @yaphets666
    一个常见的说法是"大项目更需要,小项目不必强行用"

    这谁说的?
    ------
    Vue 官方文档说的啊……
    doommm
        23
    doommm  
       2022-09-16 11:31:06 +08:00
    pinia 支持 setup 语法,切分 store 模块也比 vuex 方便太多,没理由不用的
    yaphets666
        24
    yaphets666  
       2022-09-16 13:57:40 +08:00
    @shintendo 如果您不打算开发大型单页应用,使用 Vuex 可能是繁琐冗余的。确实是如此如果您的应用够简单,您最好不要使用 Vuex 。一个简单的 store 模式就足够您所需了。但是,如果您需要构建一个中大型单页应用,您很可能会考虑如何更好地在组件外部管理状态,Vuex 将会成为自然而然的选择。引用 Redux 的作者 Dan Abramov 的话说就是:

    Flux 架构就像眼镜:您自会知道什么时候需要它。

    前端 2-3 个人,这应该不符合“你的应用够简单”这个条件吧。。。
    charlie21
        25
    charlie21  
       2022-09-16 19:40:24 +08:00
    @shakukansp 局部的业务状态共享呢用什么
    shakukansp
        26
    shakukansp  
       2022-09-16 19:57:07 +08:00
    @charlie21
    pinia
    更简单的 单独弄一个文件 export ref 变量
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2742 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 11:25 PVG 19:25 LAX 04:25 JFK 07:25
    Do have faith in what you're doing.
    ubao 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