使

使用 Vue 3 你可能不需要 Vuex

2025-05-27

使用 Vue 3 你可能不需要 Vuex

Vuex 是一个非常棒的状态管理库。它简洁易用,并且与 Vue 完美集成。为什么有人会放弃 Vuex?原因可能是即将发布的 Vue 3 版本公开了底层的响应式系统,并引入了构建应用程序的新方法。新的响应式系统非常强大,可以用于集中式状态管理。

您需要共享状态吗?

在某些情况下,多个组件之间的数据流会变得非常困难,以至于需要集中状态管理。这些情况包括:

  • 使用相同数据的多个组件
  • 具有数据访问的多个根
  • 组件深度嵌套

如果以上情况都不成立,那么答案就很简单了,不管你是否需要它。你不需要它。

但是如果你遇到这些情况怎么办?最直接的答案是使用 Vuex。它是一个久经考验的解决方案,效果不错。

但是,如果您不想添加其他依赖项,或者觉得设置过于复杂,该怎么办?新的 Vue 3 版本与 Composition API 结合使用其内置方法可以解决这些问题。

新的解决方案

共享状态必须符合两个标准:

  • 反应性:当状态改变时,使用它们的组件也应该更新
  • 可用性:可以在任何组件中访问状态

反应性

Vue 3 通过众多函数暴露了其响应式系统。你可以使用reactive函数(也可以使用ref函数)创建一个响应式变量。



import { reactive } from 'vue';

export const state = reactive({ counter: 0 });


Enter fullscreen mode Exit fullscreen mode

reactive该函数返回的对象Proxy可以跟踪其属性的变化。当在组件模板中使用时,每当响应式值发生变化时,组件都会重新渲染自身。



<template>
  <div>{{ state.counter }}</div>
  <button type="button" @click="state.counter++">Increment</button>
</template>

<script>
  import { reactive } from 'vue';

  export default {
    setup() {
      const state = reactive({ counter: 0 });
      return { state };
    }
  };
</script>


Enter fullscreen mode Exit fullscreen mode

可用性

上面的示例对于单个组件来说非常完美,但其他组件无法访问其状态。为了解决这个问题,你可以在 Vue 3 应用程序内部使用provideinject方法访问任何值。



import { reactive, provide, inject } from 'vue';

export const stateSymbol = Symbol('state');
export const createState = () => reactive({ counter: 0 });

export const useState = () => inject(stateSymbol);
export const provideState = () => provide(
  stateSymbol, 
  createState()
);


Enter fullscreen mode Exit fullscreen mode

当你将一个Symbolas 键和一个值传递给该provide方法时,该值将通过该方法供任何子组件使用。提供和检索值时,inject键使用相同的名称。Symbol

提供注入

这样,如果你在最上层的组件中提供该值,它将在所有组件中可用。或者,你也可以provide在主应用程序实例上调用。



import { createApp, reactive } from 'vue';
import App from './App.vue';
import { stateSymbol, createState } from './store';

const app = createApp(App);
app.provide(stateSymbol, createState());
app.mount('#app');


Enter fullscreen mode Exit fullscreen mode


<script>
  import { useState } from './state';

  export default {
    setup() {
      return { state: useState() };
    }
  };
</script>


Enter fullscreen mode Exit fullscreen mode

使其坚固

上述解决方案有效,但有一个缺点:你不知道谁修改了什么。状态可以直接更改,没有任何限制。

你可以用函数包装你的状态来保护它readonly。它会将传入的变量封装在一个Proxy对象中,以防止任何修改(当你尝试修改时会发出警告)。修改可以由可以访问可写存储的单独函数来处理。



import { reactive, readonly } from 'vue';

export const createStore = () => {
  const state = reactive({ counter: 0 });
  const increment = () => state.counter++;

  return { increment, state: readonly(state) };
}


Enter fullscreen mode Exit fullscreen mode

外界只能访问只读状态,只有导出的函数可以修改可写状态。

通过保护状态免受不必要的修改,新的解决方案与 Vuex 相对接近。

概括

通过使用 Vue 3 的反应系统和依赖注入机制,我们从本地状态转变为集中式状态管理,可以在较小的应用程序中取代 Vuex。

我们有一个只读的状态对象,它对模板中的更改具有响应性。该状态只能通过 Vuex 中的 action/mutations 等特定方法进行修改。您可以使用该computed函数定义其他 getter。

Vuex 具有更多功能,例如模块处理,但有时我们不需要这些功能。

如果您想了解 Vue 3 并尝试这种状态管理方法,请查看我的 Vue 3 游乐场。

GitHub 徽标 sonicoder86 / vue-3-playground

Vue 3 Playground 包含所有新功能

文章来源:https://dev.to/sonicoder/you-might-not-need-vuex-with-vue-3-52e4
PREV
简单的 Javascript 模块 - 本地存储模块
NEXT
Vue 3 升级指南