Pinia/Vuex интеграция

Naive UI представляет собой современную библиотеку компонентов для Vue 3 с упором на гибкость, минимализм и полную поддержку Composition API. Для полноценного управления состоянием приложения часто используется Pinia или Vuex. Их интеграция с Naive UI позволяет создавать динамические интерфейсы с реактивными элементами, синхронизированными со стором.


Работа с Pinia

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

Создание стора

import { defineStore } from 'pinia';

export const useCounterStore = defineStore('counter', {
  state: () => ({
    count: 0,
    loading: false,
  }),
  actions: {
    increment() {
      this.count++;
    },
    async incrementAsync() {
      this.loading = true;
      await new Promise(resolve => setTimeout(resolve, 1000));
      this.count++;
      this.loading = false;
    }
  },
});
  • state: описывает реактивное состояние.
  • actions: методы для изменения состояния, могут быть асинхронными.
  • getters (опционально): вычисляемые свойства, зависящие от состояния.

Использование Pinia с Naive UI компонентами

<template>
  <n-button @click="increment" :loading="loading">Увеличить</n-button>
  <n-tag>{{ count }}</n-tag>
</template>

<script setup>
import { useCounterStore } from '@/stores/counter';
import { storeToRefs } from 'pinia';
import { NButton, NTag } from 'naive-ui';

const counterStore = useCounterStore();
const { count, loading } = storeToRefs(counterStore);

function increment() {
  counterStore.increment();
}
</script>
  • storeToRefs используется для реактивного связывания состояния стора с компонентами Naive UI.
  • Атрибут :loading компонентов Naive UI позволяет легко интегрировать асинхронные действия стора с визуальной обратной связью.

Реактивные формы с Naive UI и Pinia

Naive UI предлагает компоненты n-input, n-select, n-form и другие, которые отлично работают с Pinia через v-model.

<n-form :model="formStore.formData">
  <n-form-item label="Имя">
    <n-input v-model:value="formStore.formData.name" />
  </n-form-item>
  <n-form-item label="Возраст">
    <n-input-number v-model:value="formStore.formData.age" />
  </n-form-item>
</n-form>
  • formStore.formData — реактивный объект в Pinia.
  • Любые изменения в форме автоматически синхронизируются с состоянием стора.

Работа с Vuex

Для проектов на Vue 2 или Vue 3 с классическим подходом по-прежнему актуален Vuex. Его интеграция с Naive UI похожа на работу с Pinia, но используется mapState, mapActions и computed.

Пример модуля Vuex

export const counterModule = {
  namespaced: true,
  state: () => ({
    count: 0,
    loading: false,
  }),
  mutations: {
    increment(state) {
      state.count++;
    },
    setLoading(state, payload) {
      state.loading = payload;
    }
  },
  actions: {
    async incrementAsync({ commit }) {
      commit('setLoading', true);
      await new Promise(resolve => setTimeout(resolve, 1000));
      commit('increment');
      commit('setLoading', false);
    }
  },
  getters: {
    doubleCount: state => state.count * 2
  }
};

Использование Vuex с Naive UI компонентами

<template>
  <n-button @click="incrementAsync" :loading="loading">Увеличить</n-button>
  <n-tag>{{ count }}</n-tag>
</template>

<script setup>
import { computed } from 'vue';
import { useStore } from 'vuex';
import { NButton, NTag } from 'naive-ui';

const store = useStore();

const count = computed(() => store.state.counter.count);
const loading = computed(() => store.state.counter.loading);

function incrementAsync() {
  store.dispatch('counter/incrementAsync');
}
</script>
  • Использование computed позволяет реактивно отслеживать состояние Vuex и автоматически обновлять компоненты Naive UI.
  • Атрибут :loading синхронизируется с состоянием стора для визуальной обратной связи.

Реактивные уведомления и Naive UI

Компоненты уведомлений, такие как n-notification или n-message, могут быть связаны с состоянием стора для автоматического информирования пользователя о событиях.

import { useCounterStore } from '@/stores/counter';
import { createDiscreteApi } from 'naive-ui';

const { message } = createDiscreteApi(['message']);
const counterStore = useCounterStore();

watch(() => counterStore.count, (newValue) => {
  if (newValue % 5 === 0) {
    message.success(`Счетчик достиг ${newValue}`);
  }
});
  • createDiscreteApi позволяет использовать уведомления вне шаблона.
  • watch реактивно следит за состоянием стора, что позволяет автоматически запускать уведомления при изменении данных.

Сводка принципов интеграции

  • Naive UI компоненты полностью поддерживают реактивные объекты стора через v-model и storeToRefs.
  • Pinia предлагает более современный и модульный подход к управлению состоянием.
  • Vuex по-прежнему применим для крупных приложений с устоявшейся архитектурой.
  • Асинхронные действия стора легко интегрируются с компонентами через :loading и уведомления.
  • Рекомендуется использовать реактивные объекты для форм, таблиц и интерактивных элементов для полной синхронизации UI и состояния.

Naive UI совместно с Pinia или Vuex обеспечивает гибкую, реактивную и легко масштабируемую архитектуру интерфейса в современных Vue-приложениях.