您可能不需要使用Vue 3的Vuex

980 阅读4分钟

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

您是否需要共享状态?

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

使用相同数据的多个组件 具有数据访问权限的多个根 组件的深层嵌套 如果以上情况都不成立,那么不管您是否需要,答案都很简单。不用了

但是,如果您有以下一种情况呢?最直接的答案是使用Vuex。这是经过考验的解决方案,并且做得不错。

但是,如果您不想添加其他依赖项或发现设置过于复杂怎么办?新的Vue 3版本以及Composition API可以通过其内置方法解决这些问题。

新的解决方案

共享状态必须符合两个条件:

反应性:当状态改变时,使用它们的组件也应更新 可用性:可以在任何组件中访问状态 反应性 Vue 3通过众多功能公开了其反应系统。您可以使用reactive函数创建反应变量(替代方法是ref函数)。

import { reactive } from 'vue';

export const state = reactive({ counter0 });

从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({ counter0 });
      return { state };
    }
  };
</script>

可用性

上面的示例对于单个组件非常有用,但是其他组件无法访问状态。为了克服这个问题,您可以使用provide和inject方法在Vue 3应用程序中提供任何可用值。

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

export const stateSymbol = Symbol('state');
export const createState = () => reactive({ counter0 });

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

当您将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');
<script>
  import { useState } from './state';

  export default {
    setup() {
      return { stateuseState() };
    }
  };
</script>

使其坚固

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

您可以通过使用readonly函数包装状态来使其受到保护。它在Proxy防止任何修改的对象中覆盖了传递的变量(尝试时会发出警告)。可以通过可访问可写存储的单独功能来处理突变。

import { reactive, readonly } from 'vue';

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

  return { increment, statereadonly(state) };
}

外部世界将只能访问只读状态,并且只有导出的函数才能修改可写状态。

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

摘要

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

我们有一个状态对象,该对象是只读的,并且对模板的更改有反应。只能通过Vuex中的动作/突变等特定方法来修改状态。您可以使用computed函数定义其他获取器。

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

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