Интеграция с Pinia

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

npm install pinia

После установки Pinia, необходимо подключить его в корневом файле приложения main.js или main.ts:

import { createApp } from 'vue';
import { createPinia } from 'pinia';
import App from './App.vue';
import ElementPlus from 'element-plus';
import 'element-plus/dist/index.css';

const app = createApp(App);
const pinia = createPinia();

app.use(pinia);
app.use(ElementPlus);
app.mount('#app');

Теперь Pinia полностью интегрирован с приложением, и можно создавать хранилища для управления состоянием.


Создание хранилища Pinia

Хранилище создается с помощью функции defineStore. Для управления элементами интерфейса Element Plus удобно хранить состояние, например, модальных окон, уведомлений или таблиц.

import { defineStore } from 'pinia';

export const useUiStore = defineStore('ui', {
  state: () => ({
    dialogVisible: false,
    loading: false,
    notification: {
      message: '',
      type: 'success'
    }
  }),
  actions: {
    openDialog() {
      this.dialogVisible = true;
    },
    closeDialog() {
      this.dialogVisible = false;
    },
    setLoading(value) {
      this.loading = value;
    },
    notify(message, type = 'success') {
      this.notification.message = message;
      this.notification.type = type;
    }
  }
});

Ключевые моменты:

  • state определяет реактивные свойства.
  • actions содержат методы для изменения состояния.
  • Хранилище можно использовать в любых компонентах, что позволяет централизованно управлять интерфейсом.

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

Управление диалогами

Компоненты Element Plus, такие как ElDialog, легко управляются через хранилище Pinia:

<template>
  <el-button @click="uiStore.openDialog">Открыть диалог</el-button>

  <el-dialog :visible.sync="uiStore.dialogVisible" title="Пример">
    <p>Содержимое диалога</p>
    <span slot="footer" class="dialog-footer">
      <el-button @click="uiStore.closeDialog">Закрыть</el-button>
    </span>
  </el-dialog>
</template>

<script setup>
import { useUiStore } from '@/stores/ui';
const uiStore = useUiStore();
</script>

Особенности интеграции:

  • :visible.sync связывает состояние диалога с реактивным свойством хранилища.
  • Любой компонент может изменять состояние диалога, не создавая локальные переменные.

Управление уведомлениями

Element Plus предоставляет ElNotification для отображения уведомлений:

import { ElNotification } from 'element-plus';
import { useUiStore } from '@/stores/ui';

const uiStore = useUiStore();

function showNotification() {
  ElNotification({
    title: 'Уведомление',
    message: uiStore.notification.message,
    type: uiStore.notification.type
  });
}

Можно расширить хранилище Pinia, чтобы автоматически отображать уведомления при изменении состояния.


Интеграция с таблицами Element Plus

При работе с ElTable удобно хранить данные, состояние загрузки и фильтры в хранилище Pinia:

import { defineStore } from 'pinia';

export const useTableStore = defineStore('table', {
  state: () => ({
    data: [],
    loading: false,
    filters: {}
  }),
  actions: {
    async fetchData() {
      this.loading = true;
      try {
        // пример запроса к API
        const response = await fetch('/api/items');
        this.data = await response.json();
      } finally {
        this.loading = false;
      }
    },
    setFilter(key, value) {
      this.filters[key] = value;
    }
  }
});

Компонент таблицы может использовать хранилище напрямую:

<template>
  <el-table :data="tableStore.data" v-loading="tableStore.loading">
    <el-table-column prop="name" label="Название" />
    <el-table-column prop="price" label="Цена" />
  </el-table>
</template>

<script setup>
import { useTableStore } from '@/stores/table';
const tableStore = useTableStore();
tableStore.fetchData();
</script>

Преимущества подхода:

  • Централизованное управление состоянием таблиц и загрузки.
  • Возможность делиться состоянием между компонентами, фильтрами и пагинацией.
  • Простая интеграция с API через actions.

Реактивность и отслеживание изменений

Pinia предоставляет возможность отслеживать реактивные свойства с помощью watch или store.$subscribe. Это полезно для автоматического обновления компонентов Element Plus при изменении состояния:

import { watch } from 'vue';
import { useUiStore } from '@/stores/ui';

const uiStore = useUiStore();

watch(() => uiStore.notification.message, (newMessage) => {
  if (newMessage) {
    ElNotification({
      title: 'Уведомление',
      message: newMessage,
      type: uiStore.notification.type
    });
  }
});

Использование Composition API с Pinia

Преимущество Pinia заключается в полной совместимости с Composition API. Это позволяет использовать ref, computed и другие реактивные инструменты для интеграции с Element Plus:

import { computed } from 'vue';
import { useTableStore } from '@/stores/table';

const tableStore = useTableStore();
const filteredData = computed(() => {
  return tableStore.data.filter(item => item.name.includes(tableStore.filters.name || ''));
});

filteredData можно использовать напрямую в ElTable, что делает реактивное обновление таблиц максимально удобным.


Итоговые рекомендации по интеграции

  • Сохранять все UI-состояния (диалоги, уведомления, таблицы) в хранилищах Pinia для единого источника правды.
  • Использовать actions для асинхронных операций, таких как API-запросы.
  • Применять computed и watch для реактивного взаимодействия с компонентами Element Plus.
  • Структурировать хранилища по функциональным блокам, чтобы поддерживать читаемость и масштабируемость кода.

Интеграция Pinia с Element Plus обеспечивает высокую управляемость состояния и упрощает разработку сложных интерфейсов на Vue 3.