Vue 3 提供了一系列内置组件,无需注册即可在任何组件中使用。这些组件覆盖了常见场景如动态组件、过渡动画、内容分发等。下面是对每个内置组件的详细说明和代码示例:
1. <component>
- 动态组件
作用 :动态切换不同的组件
核心属性:
is
:指定要渲染的组件(组件名、选项对象或HTML标签)
html
<template>
<component :is="currentComponent"></component>
<button @click="toggle">切换组件</button>
</template>
<script setup>
import { ref, shallowRef } from 'vue'
import CompA from './CompA.vue'
import CompB from './CompB.vue'
const components = [CompA, CompB]
const currentIndex = ref(0)
const currentComponent = shallowRef(components[0])
function toggle() {
currentIndex.value = (currentIndex.value + 1) % components.length
currentComponent.value = components[currentIndex.value]
}
</script>
2. <keep-alive>
- 组件缓存
作用 :缓存不活动的组件实例,避免重复渲染
核心属性:
include
:匹配的组件会被缓存(字符串/正则/数组)exclude
:匹配的组件不会被缓存max
:最大缓存实例数
html
<template>
<keep-alive :include="['CompA']" :max="5">
<component :is="currentComponent"></component>
</keep-alive>
</template>
<script setup>
// 被缓存的组件会触发:
// - activated:激活时
// - deactivated:停用时
</script>
3. <transition>
- 单元素过渡
作用 :为单个元素/组件添加进入/离开过渡
核心属性:
name
:自动生成CSS类名前缀mode
:过渡模式(out-in
/in-out
)appear
:初始渲染是否应用过渡
html
<template>
<button @click="show = !show">切换</button>
<transition
name="fade"
mode="out-in"
@before-enter="onBeforeEnter"
@after-enter="onAfterEnter">
<div v-if="show" class="box">内容</div>
</transition>
</template>
<style>
.fade-enter-active, .fade-leave-active {
transition: opacity 0.5s, transform 0.5s;
}
.fade-enter-from, .fade-leave-to {
opacity: 0;
transform: translateY(20px);
}
</style>
4. <transition-group>
- 列表过渡
作用 :为多个元素/组件添加过渡,特别适用于v-for
列表
核心特性:
- 默认渲染为
<span>
,可通过tag
指定元素类型 - 每个元素必须有独立的
key
html
<template>
<transition-group name="list" tag="ul">
<li v-for="item in items" :key="item.id">
{{ item.text }}
<button @click="remove(item)">删除</button>
</li>
</transition-group>
</template>
<style>
.list-move { /* 移动动画 */
transition: transform 0.8s ease;
}
.list-enter-active, .list-leave-active {
transition: all 0.5s;
}
.list-enter-from, .list-leave-to {
opacity: 0;
transform: translateX(30px);
}
.list-leave-active {
position: absolute;
}
</style>
5. <teleport>
- 内容传送
作用 :将内容渲染到DOM中的其他位置
核心属性:
to
:目标容器(CSS选择器或DOM元素)disabled
:是否禁用传送
html
<template>
<!-- 将模态框传送到body末尾 -->
<teleport to="body">
<div v-if="showModal" class="modal">
<h2>模态框标题</h2>
<button @click="showModal = false">关闭</button>
</div>
</teleport>
</template>
<script setup>
import { ref } from 'vue'
const showModal = ref(false)
</script>
<style>
.modal {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 9999;
}
</style>
6. <slot>
- 内容分发
作用 :在组件中定义内容插槽
核心用法:
- 默认插槽
- 具名插槽
- 作用域插槽
父组件:
html
<ChildComponent>
<template #header="{ title }">
<h1>{{ title }}</h1>
</template>
<template #default>
<p>主要内容</p>
</template>
<template #footer>
<footer>页脚信息</footer>
</template>
</ChildComponent>
子组件:
html
<template>
<div class="container">
<header>
<slot name="header" title="页面标题"></slot>
</header>
<main>
<slot>默认内容</slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
</template>
7. <suspense>
- 异步组件(实验性)
作用 :协调异步依赖的加载状态
核心插槽:
#default
:异步组件内容#fallback
:加载中状态
html
<template>
<suspense>
<template #default>
<AsyncComponent />
</template>
<template #fallback>
<div class="loading">加载中...</div>
</template>
</suspense>
</template>
<script setup>
import { defineAsyncComponent } from 'vue'
const AsyncComponent = defineAsyncComponent(() =>
import('./AsyncComponent.vue')
)
</script>
使用技巧与最佳实践
-
组合使用:
html<keep-alive> <transition name="fade" mode="out-in"> <component :is="currentView"></component> </transition> </keep-alive>
-
性能优化:
- 对
<keep-alive>
使用max
属性限制缓存数量 - 使用
shallowRef
处理动态组件避免不必要的响应式开销
- 对
-
动画优化:
css/* 启用GPU加速 */ .v-move { transition: transform 0.5s; will-change: transform; }
-
Teleport 最佳实践:
html<!-- 动态目标容器 --> <teleport :to="isMobile ? '#mobile-container' : '#desktop-container'"> <!-- 内容 --> </teleport>
-
插槽进阶用法:
html<!-- 作用域插槽传值 --> <template #item="{ data, index }"> <div :class="{ active: index === currentIndex }">{{ data.name }}</div> </template>
注意事项
<transition-group>
需要为每个元素设置唯一key
<teleport>
的目标容器必须在组件挂载前存在<suspense>
目前仍是实验性功能,API可能变更- 动态组件的
is
属性支持组件对象、组件名或HTML标签名 - 使用
<keep-alive>
时,组件会触发activated
和deactivated
生命周期钩子