Ответ
В Vue есть несколько способов создания динамических компонентов:
<component :is>- основной способ:
<component :is="currentComponent" />
currentComponent может быть строкой с именем компонента или самим импортированным компонентом.
- Динамический импорт + defineAsyncComponent (для ленивой загрузки):
const AsyncComp = defineAsyncComponent(() => import('./AsyncComp.vue'))
- Рендер-функции (для сложной логики):
render() {
return h(resolveComponent(this.componentName))
}
- Фабричные компоненты - когда компонент создаётся программно:
const component = defineComponent({...})
createApp(component).mount('#app')
Для переключения между компонентами часто используют v-if/v-else или keep-alive для сохранения состояния.
Ответ 18+ 🔞
А, ну это ж классика, блядь! Vue и его динамические компоненты — это как цирк с конями, только вместо лошадей — твои мозги, которые пытаются понять, какой хуй из трёх способов выбрать. Слушай сюда, разжуём по полочкам, а то ты, я смотрю, уже глаза квадратные делаешь.
Первый способ — <component :is>, это как швейцарский нож, только для компонентов. Кидаешь ему либо строку с именем, либо сам импортированный объект компонента, и он тебе, сука, материализует что надо. Проще пареной репы, если, конечно, не забыл компонент зарегистрировать или импортнуть.
<template>
<component :is="currentComponent" />
</template>
Смотри, currentComponent — это может быть просто строка 'MyComponent' (главное, чтоб компонент был глобальный или в components прописан), а может и прямо импортированный объект. Vue, блядь, умный, он разберётся.
Второй способ — для хитрожопых, которые хотят всё оптимизировать. Динамический импорт + defineAsyncComponent. Это когда твой компонент грузится только тогда, когда на него, блядь, посмотрят. Как стеснительная девка на танцах.
import { defineAsyncComponent } from 'vue'
const AsyncComp = defineAsyncComponent(() =>
import('./AsyncComp.vue')
)
Создал такую асинхронную хуйню — и потом можешь её в том же <component :is="AsyncComp"> пихать. Браузер не будет грузить этот файл, пока компонент не понадобится. Умно, да? Аж волосы дыбом, блядь.
Третий способ — для шаманов и ебанатров, которые любят всё через жопу. Рендер-функции. Это когда тебе мало этого прекрасного шаблонного синтаксиса, и ты хочешь, чтобы у тебя в коде была чистая JavaScript-магия, ёпта.
export default {
render() {
// h — это createElement, если что. А resolveComponent найдёт твой компонент по имени.
return h(resolveComponent(this.componentName))
}
}
Используется, когда логика выбора компонента такая ебнутая, что в шаблоне её не опишешь без трёх бутылок валерьянки. Сидишь и колдуешь, блядь.
Четвёртый способ — фабричные компоненты. Это уже для продвинутых ебланов, которые компоненты как пельмени лепят на лету, программно. defineComponent создал, createApp ему скормил, mount на элемент — и поехали, новый инстанс в DOM-дереве болтается.
const component = defineComponent({
template: '<div>Я создан из воздуха, блядь!</div>'
})
createApp(component).mount('#app')
И да, чувак, не забудь про <keep-alive>, это же пиздец как важно! Завернёшь в него свой динамический компонент — и Vue не будет его каждый раз сносить и создавать заново, а сохранит состояние, как дорогой коньяк. Иначе все твои инпуты, скроллы и прочая хуйня будет сбрасываться при каждом переключении. А кому это надо?
<keep-alive>
<component :is="currentComponent" />
</keep-alive>
Ну и v-if с v-else для переключения — это как два кнопки: одна включает свет, другая выключает. Примитивно, но работает, если варианта всего два.
Вот и вся философия, блядь. Выбирай способ по степени своего ебланизма и иди кодить. Главное — не перемудри, а то опять всю ночь будешь дебажить, почему компонент не показывается, а он, оказывается, с маленькой буквы написан.