Вам возможно не нужен Vuex с Vue 3

Spread the love

Оригинальная статья: Gábor SoósYou Might Not Need Vuex with Vue 3

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

Вам нужно общее состояние?

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

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

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

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

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

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

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

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

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

import { reactive } from 'vue';

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

Объект, возвращаемый из функции 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>

Доступность

Приведенный выше пример отлично подходит для одного компонента, но другие компоненты не могут получить доступ к состоянию. Чтобы преодолеть это, вы можете сделать любое значение доступным в приложении 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()
);

Когда вы передаете Symbol в качестве ключа и значение в метод provide, это значение будет доступно для любого дочернего компонента через метод inject. Ключ использует то же имя Symbol при предоставлении (providing) и получении (retrieving) значения.

provide inject

Таким образом, если вы предоставите (provide) значение для самого верхнего компонента, оно будет доступно во всех компонентах. Кроме того, вы также можете вызвать 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) };
}

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

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

Заключение

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

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

Vuex имеет больше функционала, для обработки модулей, но чаще всего нам это не нужно.

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

Была ли вам полезна эта статья?
[9 / 5]

Spread the love
Подписаться
Уведомление о
guest
2 Комментарий
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Анонимно
Анонимно
3 лет назад

> взгляните на мою площадку Vue 3.
Всё же – песочницу.

Хороший коТ
Хороший коТ
3 лет назад

Нам нужен. Особенно в средних и крупных приложениях.
Кстати, в третей версии, как в Nuxt.js, могли-бы включить Vuex по-умолчанию. Или, хотя-бы, при инициализации спросить, предустанавливать или нет..