Динамические компоненты во Vue.js

Динамические компоненты во Vue.js Vue.js

Динамические компоненты — это мощный механизм Vue.js, позволяющий переключать компоненты «на лету». Они особенно полезны при создании интерфейсов с вкладками, мастеров настройки или любых других случаях, когда необходимо динамически менять содержимое

Component и :is

Базовое использование

Компонент <component> с атрибутом is позволяет динамически переключать компоненты:

<template>
  <div>
    <button 
      v-for="tab in tabs" 
      :key="tab"
      @click="currentTab = tab"
    >
      {{ tab }}
    </button>

    <component :is="currentTab"></component>
  </div>
</template>

<script>
import TabHome from './components/TabHome.vue'
import TabPosts from './components/TabPosts.vue'
import TabArchive from './components/TabArchive.vue'

export default {
  components: {
    TabHome,
    TabPosts,
    TabArchive
  },
  data() {
    return {
      currentTab: 'TabHome',
      tabs: ['TabHome', 'TabPosts', 'TabArchive']
    }
  }
}
</script>

Передача пропсов

Динамическим компонентам можно передавать пропсы:

<component 
  :is="currentTab"
  :title="tabTitle"
  @custom-event="handleEvent"
/>

Keep-alive

Сохранение состояния компонента

<keep-alive> позволяет сохранять состояние компонентов при переключении:

<template>
  <div>
    <keep-alive>
      <component :is="currentTab"></component>
    </keep-alive>
  </div>
</template>

Включение/исключение компонентов

Можно указать, какие компоненты нужно кэшировать:

<keep-alive :include="['TabHome', 'TabPosts']" :exclude="['TabArchive']">
  <component :is="currentTab"></component>
</keep-alive>

Хуки жизненного цикла

При использовании keep-alive доступны специальные хуки:

export default {
  name: 'TabHome',
  activated() {
    // Вызывается при восстановлении компонента из кэша
    console.log('Component activated')
  },
  deactivated() {
    // Вызывается при помещении компонента в кэш
    console.log('Component deactivated')
  }
}

Асинхронные компоненты

Базовая загрузка

Асинхронная загрузка компонентов для оптимизации производительности:

<script>
export default {
  components: {
    AsyncComponent: () => import('./AsyncComponent.vue')
  }
}
</script>

Продвинутая конфигурация

Настройка загрузки с обработкой состояний:

const AsyncComponent = () => ({
  component: import('./AsyncComponent.vue'),
  loading: LoadingComponent,
  error: ErrorComponent,
  delay: 200,
  timeout: 3000
})

Transitions

Базовые переходы

Анимация при переключении компонентов:

<template>
  <transition name="fade">
    <component :is="currentTab"></component>
  </transition>
</template>

<style>
.fade-enter-active, .fade-leave-active {
  transition: opacity 0.3s ease;
}
.fade-enter-from, .fade-leave-to {
  opacity: 0;
}
</style>

Режимы перехода

<transition name="fade" mode="out-in">
  <component :is="currentTab"></component>
</transition>

Slots

Базовые слоты

Использование слотов для гибкой компоновки:

<!-- BaseLayout.vue -->
<template>
  <div class="container">
    <header>
      <slot name="header"></slot>
    </header>
    <main>
      <slot></slot>
    </main>
    <footer>
      <slot name="footer"></slot>
    </footer>
  </div>
</template>

<!-- Использование -->
<base-layout>
  <template v-slot:header>
    <h1>Заголовок</h1>
  </template>

  <template v-slot:default>
    <p>Основной контент</p>
  </template>

  <template v-slot:footer>
    <p>Подвал</p>
  </template>
</base-layout>

Скоупированные слоты

Передача данных через слоты:

<!-- ItemList.vue -->
<template>
  <ul>
    <li v-for="item in items" :key="item.id">
      <slot :item="item">
        {{ item.text }}
      </slot>
    </li>
  </ul>
</template>

<!-- Использование -->
<item-list :items="items">
  <template v-slot:default="slotProps">
    <strong>{{ slotProps.item.text }}</strong>
  </template>
</item-list>

Телепортация компонентов

Базовое использование

Телепортация содержимого в другую часть DOM:

<template>
  <div>
    <teleport to="body">
      <div class="modal">
        <h2>Модальное окно</h2>
        <slot></slot>
        <button @click="closeModal">Закрыть</button>
      </div>
    </teleport>
  </div>
</template>

Условная телепортация

<teleport to="#modal" :disabled="!shouldTeleport">
  <div class="modal">
    <!-- содержимое модального окна -->
  </div>
</teleport>

Практический пример

Создадим табы с анимированным переключением и сохранением состояния:

<template>
  <div class="tabs-container">
    <div class="tabs-buttons">
      <button 
        v-for="tab in tabs" 
        :key="tab.name"
        :class="['tab-button', { active: currentTab === tab.name }]"
        @click="currentTab = tab.name"
      >
        {{ tab.label }}
      </button>
    </div>

    <keep-alive>
      <transition name="fade" mode="out-in">
        <component 
          :is="currentTab"
          :data="tabData"
          @update="handleUpdate"
        ></component>
      </transition>
    </keep-alive>

    <teleport to="#modal-container" v-if="showModal">
      <div class="modal">
        <!-- Модальное окно -->
      </div>
    </teleport>
  </div>
</template>

<script>
export default {
  data() {
    return {
      currentTab: 'TabHome',
      showModal: false,
      tabs: [
        { name: 'TabHome', label: 'Главная' },
        { name: 'TabPosts', label: 'Посты' },
        { name: 'TabArchive', label: 'Архив' }
      ],
      tabData: {}
    }
  },
  methods: {
    handleUpdate(data) {
      this.tabData = data
    }
  }
}
</script>

<style scoped>
.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.3s ease;
}

.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}

.tab-button {
  padding: 10px 20px;
  margin: 5px;
  border: none;
  cursor: pointer;
}

.tab-button.active {
  background-color: #42b983;
  color: white;
}
</style>

Еще больше уроков для изучения Vue

Оцените статью
Уроки программирования
0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest
0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x