Рубрики
Без рубрики

Возможно, вам не понадобится Vuex с Vue 3

Vuex – это потрясающая библиотека управления состояниями. Она проста и хорошо интегрируется с Vue. Зачем кому-то уходить от Vuex в Vue 3?

Vuex – это потрясающая библиотека управления состояниями. Она проста и хорошо интегрируется с Vue. Зачем кому-то уходить от Vuex? Причина может быть в том, что предстоящий релиз Vue 3 раскроет лежащую в основе систему реактивности и представит новые способы структурирования приложения. Новая система реактивности настолько мощная, что ее можно использовать для централизованного управления состояниями.

Нужно ли вам общее состояние?

Бывают обстоятельства, когда поток данных между несколькими компонентами становится настолько сложным, что вам необходимо централизованное управление состоянием. К таким обстоятельствам относятся:

  • Несколько компонентов, использующих одни и те же данные
  • Несколько корней с доступом к данным
  • Глубокая вложенность компонентов

Если ни один из вышеперечисленных случаев не верен, ответ прост, независимо от того, нужно вам это или нет. Вам это не нужно.

Но как быть, если у вас есть один из этих случаев? Прямым ответом будет использование Vuex. Это проверенное в боях решение, которое делает достойную работу.

Но что делать, если вы не хотите добавлять еще одну зависимость или считаете настройку слишком сложной? Новая версия Vue 3 вместе с Composition API может решить эти проблемы с помощью своих встроенных методов.

Новое решение

Общее состояние должно соответствовать двум критериям:

  • реактивность: когда состояние изменяется, компоненты, использующие его, также должны обновляться
  • доступность: к состоянию можно получить доступ в любом из компонентов.

Реактивность

Vue 3 раскрывает свою систему реактивности через множество функций. Вы можете создать реактивную переменную с помощью функции reactive (альтернативой может быть функция ref).

import { reactive } from 'vue';

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

Объект, возвращаемый из функции reactive, является объектом Proxy, который может отслеживать изменения своих свойств. При использовании в шаблоне компонента компонент перерисовывается каждый раз, когда изменяется значение функции reactive.

<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>

Доступность

Приведенный выше пример отлично подходит для одного компонента, но другие компоненты не могут получить доступ к состоянию. Чтобы решить эту проблему, вы можете сделать любое значение доступным внутри приложения Vue 3 с помощью методов provide и inject.

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()
);

Когда вы передаете Символ в качестве ключа и значение в метод 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 { state: useState() };
    }
  };
</script>

Обеспечение надежности

Приведенное выше решение работает, но имеет недостаток: вы не знаете, кто и что изменяет. Состояние может быть изменено напрямую, и здесь нет никаких ограничений.

Вы можете сделать состояние защищенным, обернув его функцией readonly. Она закрывает переданную переменную в объекте Proxy, который предотвращает любые изменения (выдает предупреждение, когда вы пытаетесь это сделать). Мутации могут обрабатываться отдельными функциями, имеющими доступ к хранилищу с возможностью записи.

import { reactive, readonly } from 'vue';

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

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

Внешний мир будет иметь доступ только к состоянию, доступному для чтения, и только экспортируемые функции могут изменять состояние, доступное для записи.

Защищая состояние от нежелательных модификаций, новое решение относительно близко к Vuex.

Резюме

Используя систему реактивности и механизм инъекции зависимостей Vue 3, мы перешли от локального состояния к централизованному управлению состоянием, которое может заменить Vuex в небольших приложениях.

У нас есть объект состояния, который доступен только для чтения и реагирует на изменения в шаблонах. Состояние может быть изменено только с помощью специальных методов, таких как actions/mutations в Vuex. Вы можете определить дополнительные геттеры с помощью вычисляемой (computed) функции.

Vuex имеет больше возможностей, таких как обработка модулей, но иногда нам это не нужно.

Если вы хотите взглянуть на Vue 3 и попробовать этот подход к управлению состоянием, посмотрите на мою игровую площадку Vue 3.

Оригинал: “https://www.codementor.io/@soosgabor86/you-might-not-need-vuex-with-vue-3-1ell156wi1”