Element Plus предоставляет мощный набор компонентов для построения интерфейсов на Vue 3. Часто возникает необходимость не просто использовать стандартные компоненты, а расширять их функциональность, подстраивая под специфические требования проекта. Расширение компонентов позволяет сохранять консистентность дизайна, повторно использовать логику и избегать дублирования кода.
extendsElement Plus поддерживает возможность наследования компонентов Vue 3. Это позволяет создавать новый компонент на основе существующего, сохраняя его базовую функциональность и стили, добавляя новые методы, свойства или события.
Пример: расширение кнопки ElButton
import { defineComponent } from 'vue';
import { ElButton } from 'element-plus';
export default defineComponent({
name: 'CustomButton',
extends: ElButton,
props: {
highlight: {
type: Boolean,
default: false
}
},
computed: {
buttonClasses() {
return {
'custom-highlight': this.highlight,
...this.$attrs.class
};
}
},
template: `
<el-button v-bind="$attrs" :class="buttonClasses">
<slot></slot>
</el-button>
`
});
В данном примере создаётся компонент CustomButton,
который наследует все свойства и события ElButton, а также
добавляется новое свойство highlight, позволяющее применять
дополнительный стиль.
Ключевой момент: использование extends
сохраняет реактивность исходного компонента и его встроенные методы.
Element Plus активно использует слоты для передачи пользовательского контента. Расширение компонента может включать добавление новых слотов или изменение поведения существующих.
Пример: расширение ElTable с кастомным слотом
для колонок
import { defineComponent } from 'vue';
import { ElTable, ElTableColumn } from 'element-plus';
export default defineComponent({
name: 'CustomTable',
components: { ElTable, ElTableColumn },
props: {
data: {
type: Array,
required: true
}
},
template: `
<el-table :data="data">
<slot name="columns">
<el-table-column prop="name" label="Имя"></el-table-column>
<el-table-column prop="age" label="Возраст"></el-table-column>
</slot>
</el-table>
`
});
С помощью слота columns можно полностью контролировать
набор колонок при использовании компонента, не изменяя исходную
структуру таблицы.
Важно: использование именованных слотов позволяет расширяемым компонентам быть максимально гибкими и совместимыми с разными вариантами контента.
provide
и injectДля передачи данных между расширяемыми компонентами удобно
использовать систему зависимостей Vue 3: provide и
inject. Это особенно полезно для создания обёрток вокруг
компонентов Element Plus, которые должны управлять состоянием нескольких
дочерних элементов.
Пример: расширение формы ElForm
import { defineComponent, provide, ref } from 'vue';
import { ElForm, ElFormItem } from 'element-plus';
export default defineComponent({
name: 'CustomForm',
components: { ElForm, ElFormItem },
setup() {
const formData = ref({});
const validateForm = () => {
console.log('Валидация формы', formData.value);
};
provide('formData', formData);
provide('validateForm', validateForm);
return { formData, validateForm };
},
template: `
<el-form :model="formData">
<slot></slot>
</el-form>
`
});
Дочерние компоненты могут получить доступ к formData и
validateForm через inject, что позволяет
централизованно управлять данными формы и валидацией.
Композиция функционала через mixin или функции
composition API является удобным способом добавления общей
логики к нескольким компонентам Element Plus.
Пример композиционной функции для уведомлений
import { ElMessage } from 'element-plus';
export function useNotify() {
const success = (msg) => {
ElMessage({ message: msg, type: 'success' });
};
const error = (msg) => {
ElMessage({ message: msg, type: 'error' });
};
return { success, error };
}
Эту функцию можно использовать в любом компоненте, расширяя его функциональность без дублирования кода:
import { defineComponent } from 'vue';
import { useNotify } from './useNotify';
import { ElButton } from 'element-plus';
export default defineComponent({
name: 'NotifyButton',
components: { ElButton },
setup() {
const { success } = useNotify();
const handleClick = () => success('Действие выполнено успешно');
return { handleClick };
},
template: `<el-button @click="handleClick">Показать уведомление</el-button>`
});
Расширение компонентов часто реализуется через обёртки, которые добавляют новые возможности, не изменяя исходный компонент напрямую. Такой подход обеспечивает совместимость с будущими обновлениями Element Plus.
Пример: обёртка для ElInput с
маской
import { defineComponent, ref } from 'vue';
import { ElInput } from 'element-plus';
export default defineComponent({
name: 'MaskedInput',
components: { ElInput },
props: {
mask: {
type: String,
required: true
}
},
setup(props, { emit }) {
const value = ref('');
const handleInput = (e) => {
// Простая маска: цифры только
value.value = e.replace(/\D/g, '');
emit('update:modelValue', value.value);
};
return { value, handleInput };
},
template: `
<el-input :value="value" @input="handleInput"></el-input>
`
});
Обёртка добавляет новую функциональность (маску ввода), сохраняя все
возможности оригинального ElInput.
props и события
через emit, избегая прямого изменения приватных методов
компонента.Расширение компонентов Element Plus с использованием этих подходов обеспечивает гибкость, масштабируемость и чистую архитектуру проекта на Vue 3.