内置组件
内置组件
在 Vue 3 中,有几个内置组件可以用于实现特定的功能,分别是 Transition、TransitionGroup、KeepAlive、Teleport 和 Suspense。
1. Transition
Transition 组件用于在元素的插入、更新或移除时添加过渡效果。它可以根据元素的插入/更新/移除状态自动应用过渡类名来触发 CSS 过渡效果。以下是一个例子:
<template>
<transition name="fade">
<div v-if="show">这是一个过渡示例</div>
</transition>
<button @click="toggleShow">切换显示</button>
</template>
<script setup>
import { ref } from "vue";
const show = ref(true);
const toggleShow = () => {
show.value = !show.value;
};
</script>
<style>
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.5s;
}
.fade-enter,
.fade-leave-to {
opacity: 0;
}
</style>
在上述例子中,我们使用<transition>
包裹了一个<div>
元素,并设置了name
属性为"fade"。当show
变量为true
时,<div>
会以淡入的方式显示;当show
变量为false
时,<div>
会以淡出的方式隐藏。
需要注意的是:
- 为
<transition>
提供一个唯一的key
属性,可以在元素插入/更新/移除时正确应用过渡效果。 - CSS 样式中的类名是根据
name
属性自动生成的,如fade-enter-active
和fade-leave-active
。类名中的-enter-active
和-leave-active
表示插入/更新/移除过程的活动状态,而-enter
和-leave-to
表示插入/更新/移除过程的开始和结束状态。
2. TransitionGroup
TransitionGroup 组件可以将多个元素一起包裹,并在它们插入/更新/移除时应用过渡效果。这个组件的使用方式与 Transition 类似,但是针对列表元素的过渡处理更加方便。以下是一个例子:
<template>
<transition-group name="list" tag="ul">
<li v-for="item in items" :key="item.id" class="list-item">
{{ item.text }}
</li>
</transition-group>
<button @click="addItem">添加项</button>
</template>
<script setup>
import { ref } from "vue";
const items = ref([
{ id: 1, text: "Item 1" },
{ id: 2, text: "Item 2" },
]);
let nextId = 3;
const addItem = () => {
items.value.push({ id: nextId, text: `Item ${nextId}` });
nextId++;
};
</script>
<style>
.list-enter-active,
.list-leave-active {
transition: all 0.5s;
}
.list-enter-from,
.list-leave-to {
opacity: 0;
transform: translateY(-30px);
}
</style>
在上述例子中,我们使用<transition-group>
作为一个<ul>
元素的容器,并给它设置了name
属性为"list"。通过使用v-for
指令,我们创建了多个<li>
元素,并为每个元素设置了动态的key
。当添加或删除项时,新的项将根据索引值插入和移除,带有过渡效果。
需要注意的是:
tag
属性用于确定过渡组件的根元素类型,默认是<span>
。- 过渡元素的位置类名是根据
name
属性自动生成的,如list-enter-active
和list-leave-active
。 - CSS 样式中的类名也有一些特殊之处,如
-enter-from
表示插入过程的初始状态,-leave-to
表示移除过程结束的状态。
3. KeepAlive
KeepAlive 组件用于缓存组件实例,以便在切换时保持其状态。常用于包含有昂贵的组件,减少不必要的初始化和渲染开销。以下是一个例子:
<template>
<div>
<button @click="toggleComponent">切换组件</button>
<keep-alive>
<component :is="currentComponent" />
</keep-alive>
</div>
</template>
<script setup>
import { ref } from "vue";
const componentA = { template: "<div>组件A</div>" };
const componentB = { template: "<div>组件B</div>" };
const currentComponent = ref(componentA);
const toggleComponent = () => {
currentComponent.value =
currentComponent.value === componentA ? componentB : componentA;
};
</script>
在上述例子中,我们使用<keep-alive>
将动态组件包裹起来。当切换时,被缓存的组件实例会保留在内存中,以减少重新创建和销毁组件的开销。
需要注意的是:
- 使用
<component>
将组件动态渲染到<keep-alive>
中。 - 需要给每个缓存的组件设置唯一的
key
属性,以便缓存和复用实例。
4. Teleport
Teleport 组件可用于将内容移到 DOM 树中的其他位置,可以用于创建模态框、弹出菜单等组件。以下是一个例子:
<template>
<div>
<button @click="toggleModal">打开模态框</button>
<teleport to="body">
<div v-if="showModal" class="modal">
<h2>这是一个模态框</h2>
<p>模态框的内容</p>
<button @click="toggleModal">关闭模态框</button>
</div>
</teleport>
</div>
</template>
<script setup>
import { ref } from "vue";
const showModal = ref(false);
const toggleModal = () => {
showModal.value = !showModal.value;
};
</script>
<style>
.modal {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 300px;
padding: 20px;
background-color: white;
border: 1px solid #ccc;
}
</style>
在上述例子中,我们使用<teleport>
将模态框的内容移到<body>
下。通过点击按钮,可以控制模态框的显示和隐藏。
需要注意的是:
- 使用
to
属性指定要移动到的目标位置的选择器或 DOM 元素。 - 被移动的内容可以是任意合法的 HTML 结构。
5. Suspense
Suspense 组件用于在异步加载组件时显示一个占位符,直到异步操作完成。这个组件通常与异步组件配合使用。以下是一个例子:
<template>
<div class="container">
<Suspense>
<template #default>
<component :is="currentComponent" />
</template>
<template #fallback>
<div class="loading">正在加载组件...</div>
</template>
</Suspense>
<button @click="toggleComponent">切换组件</button>
</div>
</template>
<script setup>
import { ref } from "vue";
const componentA = import("./ComponentA.vue");
const componentB = import("./ComponentB.vue");
const currentComponent = ref(componentA);
const toggleComponent = () => {
currentComponent.value =
currentComponent.value === componentA ? componentB : componentA;
};
</script>
<style>
.container {
position: relative;
}
.loading {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex;
justify-content: center;
align-items: center;
background-color: rgba(255, 255, 255, 0.8);
}
</style>
在上述例子中,我们使用<Suspense>
将异步组件包裹起来,并设置了两个模板。default
模板用于渲染异步组件,fallback
模板用于异步加载期间显示的占位符。
需要注意的是:
- 异步组件可以通过动态
import
函数进行异步加载,并将异步返回的模块赋值给<component>
的:is
属性。 - 当加载异步组件时,如果异步操作还没完成,将会显示
fallback
模板中的内容,直到异步操作完成后再渲染实际的组件。 - 更多异步组件参考 异步组件
以上是 Vue 3 内置组件的解释和注意事项,涵盖了 Transition、TransitionGroup、KeepAlive、Teleport 和 Suspense。通过这些组件,您可以方便地实现元素过渡效果、列表过渡效果、组件缓存、内容的移动和异步加载时的占位符显示。希望这些例子能够帮助您更好地理解和使用 Vue 3 的内置组件。
组件结合使用
我们常常会将 <Suspense>
和 <Transition>
、<KeepAlive>
等组件结合。要保证这些组件都能正常工作,嵌套的顺序非常重要。
另外,这些组件都通常与 Vue Router 中的 <RouterView>
组件结合使用。
<template>
<RouterView v-slot="{ Component }">
<Transition mode="out-in">
<KeepAlive>
<Suspense>
<!-- 主要内容 -->
<component :is="Component"></component>
<!-- 加载中状态 -->
<template #fallback>
正在加载...
</template>
</Suspense>
</KeepAlive>
</Transition>
</RouterView>
</template>