Naive UI представляет собой современную библиотеку компонентов для Vue 3 с упором на гибкость, минимализм и полную поддержку Composition API. Для полноценного управления состоянием приложения часто используется Pinia или Vuex. Их интеграция с Naive UI позволяет создавать динамические интерфейсы с реактивными элементами, синхронизированными со стором.
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;
}
},
});
<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 предлагает компоненты 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.Для проектов на Vue 2 или Vue 3 с классическим подходом по-прежнему
актуален Vuex. Его интеграция с Naive UI похожа на работу с Pinia, но
используется mapState, mapActions и
computed.
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
}
};
<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 синхронизируется с состоянием стора
для визуальной обратной связи.Компоненты уведомлений, такие как 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 реактивно следит за состоянием стора, что
позволяет автоматически запускать уведомления при изменении данных.v-model и storeToRefs.:loading и уведомления.Naive UI совместно с Pinia или Vuex обеспечивает гибкую, реактивную и легко масштабируемую архитектуру интерфейса в современных Vue-приложениях.