Композиция компонентов

Композиция компонентов в Element Plus позволяет создавать гибкие и переиспользуемые интерфейсы, объединяя готовые элементы библиотеки с собственными компонентами Vue 3. Основной подход строится на использовании слотов, props и реактивных данных, что обеспечивает максимальную адаптивность и расширяемость компонентов.


Слоты и их разновидности

Слоты — это ключевой инструмент для внедрения пользовательского содержимого внутрь компонентов Element Plus.

  • Стандартный слот (default) Используется для передачи основного содержимого. Пример:
<el-card>
  <p>Основное содержимое карточки</p>
</el-card>
  • Именованные слоты Позволяют определять несколько областей внутри компонента для разных типов контента.
<el-dialog>
  <template #title>
    Диалоговое окно
  </template>
  <template #footer>
    <el-button type="primary">Закрыть</el-button>
  </template>
</el-dialog>
  • Слоты с пропсами Компоненты Element Plus могут передавать данные через слот-пропсы, которые позволяют динамически изменять отображение внутри слота.
<el-table :data="tableData">
  <template #default="{ row }">
    <el-tag>{{ row.status }}</el-tag>
  </template>
</el-table>

Props и реактивные данные

Композиция компонентов тесно связана с props, через которые родитель передаёт настройки и данные дочерним компонентам.

  • Использование v-model для двусторонней связи:
<el-input v-model="inputValue" placeholder="Введите текст"></el-input>
  • Передача сложных объектов:
<el-table :data="users" :row-key="id">
  <el-table-column prop="name" label="Имя" width="180"></el-table-column>
</el-table>
  • Реактивность через ref и reactive из Vue 3 позволяет динамически управлять состоянием компонентов:
import { ref } from 'vue';

const visible = ref(false);

function toggleDialog() {
  visible.value = !visible.value;
}

Динамическая композиция и условный рендеринг

Элементами Element Plus можно управлять динамически, используя условный рендеринг и циклы.

  • v-if / v-else для отображения компонентов по условию:
<el-alert v-if="isError" title="Произошла ошибка" type="error"></el-alert>
  • v-for для генерации множества компонентов:
<el-tag
  v-for="tag in tags"
  :key="tag"
  type="success"
>
  {{ tag }}
</el-tag>
  • Сочетание слотов с динамическим рендерингом позволяет создавать гибкие интерфейсы:
<el-menu>
  <el-menu-item
    v-for="item in menuItems"
    :key="item.id"
  >
    {{ item.label }}
  </el-menu-item>
</el-menu>

Композиция сложных интерфейсов

Element Plus предоставляет множество компонентов, которые можно комбинировать для построения сложных интерфейсов:

  • Карточки и таблицы с действиями:
<el-card>
  <el-table :data="users">
    <el-table-column prop="name" label="Имя"></el-table-column>
    <el-table-column label="Действия">
      <template #default="{ row }">
        <el-button type="primary" @click="editUser(row)">Редактировать</el-button>
        <el-button type="danger" @click="deleteUser(row)">Удалить</el-button>
      </template>
    </el-table-column>
  </el-table>
</el-card>
  • Формы с кастомными компонентами:
<el-form :model="formData" label-width="120px">
  <el-form-item label="Имя">
    <el-input v-model="formData.name"></el-input>
  </el-form-item>
  <el-form-item label="Роль">
    <el-select v-model="formData.role" placeholder="Выберите роль">
      <el-option label="Администратор" value="admin"></el-option>
      <el-option label="Пользователь" value="user"></el-option>
    </el-select>
  </el-form-item>
</el-form>
  • Диалоги с динамическим содержимым:
<el-dialog :visible.sync="dialogVisible" title="Детали пользователя">
  <component :is="currentComponent" :data="selectedData"></component>
</el-dialog>

Расширяемость через кастомные компоненты

Компоненты Element Plus можно комбинировать с собственными Vue-компонентами для создания уникальных решений:

  • Обёртки над базовыми компонентами для стандартной стилизации или логики:
<template>
  <el-button :type="type" @click="handleClick">
    <slot></slot>
  </el-button>
</template>

<script setup>
import { defineProps, defineEmits } from 'vue';

const props = defineProps({
  type: { type: String, default: 'primary' }
});
const emit = defineEmits(['click']);

function handleClick() {
  emit('click');
}
</script>
  • Композиция с логикой управления состоянием через provide и inject:
import { provide, reactive } from 'vue';

const state = reactive({ count: 0 });
provide('counter', state);
<script setup>
import { inject } from 'vue';

const counter = inject('counter');
function increment() {
  counter.count++;
}
</script>

Взаимодействие между компонентами

Element Plus активно использует события и реактивные данные для передачи информации между компонентами:

  • Использование событий через @event:
<el-input @input="handleInput" placeholder="Введите значение"></el-input>
  • Комбинация событий с v-model для упрощённой двусторонней связи:
<el-checkbox-group v-model="selectedOptions">
  <el-checkbox label="Option 1"></el-checkbox>
  <el-checkbox label="Option 2"></el-checkbox>
</el-checkbox-group>
  • Создание сложных взаимодействий через слоты и пропсы:
<el-table :data="orders">
  <el-table-column prop="status" label="Статус">
    <template #default="{ row }">
      <el-tag :type="row.status === 'active' ? 'success' : 'info'">
        {{ row.status }}
      </el-tag>
    </template>
  </el-table-column>
</el-table>

Итоговый подход к композиции

Основная стратегия композиции компонентов в Element Plus заключается в:

  1. Разделении интерфейса на мелкие переиспользуемые компоненты.
  2. Использовании слотов и именованных слотов для гибкого наполнения контента.
  3. Передаче данных через props и реактивные объекты для динамических изменений.
  4. Применении событий и v-model для двусторонней связи.
  5. Объединении стандартных и кастомных компонентов для создания уникальных UI-модулей.

Такой подход обеспечивает структурированность кода, лёгкость поддержки и возможность быстрого расширения интерфейсов без дублирования логики.