В Element Plus для организации передачи данных между
компонентами на разных уровнях вложенности часто используется сочетание
Vue 3 API provide и inject. Это особенно
актуально при работе с формами, таблицами, модальными окнами и другими
сложными компонентами библиотеки, где требуется передача состояния или
методов без прямого пропа через все промежуточные компоненты.
provide используется в родительском
компоненте для объявления данных или функций, которые должны быть
доступны вложенным компонентам.inject позволяет дочернему компоненту
получать эти данные без явного пропа.provide, могут быть
реактивными, что позволяет автоматически обновлять дочерние компоненты
при изменении состояния.Пример базового использования:
import { ref, provide, inject } from 'vue';
export default {
setup() {
const themeColor = ref('primary');
provide('themeColor', themeColor);
return { themeColor };
}
}
// В дочернем компоненте
export default {
setup() {
const themeColor = inject('themeColor');
return { themeColor };
}
}
В этом примере дочерний компонент автоматически реагирует на
изменения themeColor в родительском компоненте.
Многие компоненты Element Plus внутри себя используют
provide/inject для управления состоянием. Рассмотрим
несколько практических сценариев.
ElForm предоставляет общий контекст для всех вложенных
ElFormItem, включая валидацию, модели данных и правила.
import { ElForm, ElFormItem, ElInput, ElButton } from 'element-plus';
export default {
components: { ElForm, ElFormItem, ElInput, ElButton },
setup() {
const formData = reactive({
username: '',
password: ''
});
const rules = reactive({
username: [{ required: true, message: 'Введите имя пользователя', trigger: 'blur' }],
password: [{ required: true, message: 'Введите пароль', trigger: 'blur' }]
});
return { formData, rules };
},
template: `
<el-form :model="formData" :rules="rules" ref="formRef">
<el-form-item label="Имя пользователя" prop="username">
<el-input v-model="formData.username"></el-input>
</el-form-item>
<el-form-item label="Пароль" prop="password">
<el-input type="password" v-model="formData.password"></el-input>
</el-form-item>
<el-button type="primary" @click="formRef.validate()">Отправить</el-button>
</el-form>
`
}
Здесь ElForm через provide передаёт объект
формы и правила в каждый ElFormItem.
ElFormItem автоматически получает эти данные с помощью
inject и выполняет валидацию без необходимости напрямую
передавать пропсы.
Можно создать компонент-обёртку, который через provide
задаёт тему или стили для всех дочерних Element Plus
компонентов:
import { provide, reactive } from 'vue';
export default {
setup() {
const themeSettings = reactive({
size: 'small',
buttonType: 'success'
});
provide('themeSettings', themeSettings);
return { themeSettings };
}
}
// В дочернем компоненте
import { inject } from 'vue';
import { ElButton } from 'element-plus';
export default {
components: { ElButton },
setup() {
const themeSettings = inject('themeSettings');
return { themeSettings };
},
template: `
<el-button :type="themeSettings.buttonType" :size="themeSettings.size">
Кнопка
</el-button>
`
}
Таким образом, изменение темы в родительском компоненте автоматически отражается на всех кнопках и компонентах, использующих этот контекст.
ElDialog часто используется совместно с
provide/inject для передачи функций открытия и закрытия
диалога:
import { ref, provide } from 'vue';
import { ElDialog, ElButton } from 'element-plus';
export default {
components: { ElDialog, ElButton },
setup() {
const isDialogVisible = ref(false);
const openDialog = () => isDialogVisible.value = true;
const closeDialog = () => isDialogVisible.value = false;
provide('dialogControl', { openDialog, closeDialog });
return { isDialogVisible };
},
template: `
<el-dialog v-model="isDialogVisible" title="Пример">
Контент модального окна
</el-dialog>
`
}
// В дочернем компоненте
import { inject } from 'vue';
import { ElButton } from 'element-plus';
export default {
components: { ElButton },
setup() {
const dialogControl = inject('dialogControl');
return { dialogControl };
},
template: `
<el-button type="primary" @click="dialogControl.openDialog()">
Открыть диалог
</el-button>
`
}
Этот подход позволяет централизованно управлять состоянием диалогов из родителя, а дочерние компоненты просто используют переданные методы.
ref или reactive. Несовместимые типы данных
могут привести к отсутствию обновлений в дочерних компонентах.inject отражаются на всех дочерних компонентах, если данные
реактивны.provide/inject работает
только внутри иерархии компонентов. Если компонент не является потомком,
он не сможет получить данные.provide/inject, чтобы избежать ошибок и
поддерживать автокомплит.provide/inject для внутренней логики, поэтому при
кастомизации этих компонентов важно учитывать существующие ключи.Использование provide/inject вместе с компонентами
Element Plus позволяет создавать гибкую архитектуру, где
данные, методы и состояния могут быть централизованно переданы и
реактивно обновляться на любом уровне вложенности. Это значительно
упрощает разработку крупных интерфейсов с повторно используемыми и
настраиваемыми компонентами.