Skip to content
📈0️⃣

内置组件

内置组件

在 Vue 3 中,有几个内置组件可以用于实现特定的功能,分别是 Transition、TransitionGroup、KeepAlive、Teleport 和 Suspense。

1. Transition

Transition 组件用于在元素的插入、更新或移除时添加过渡效果。它可以根据元素的插入/更新/移除状态自动应用过渡类名来触发 CSS 过渡效果。以下是一个例子:

vue
<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-activefade-leave-active。类名中的-enter-active-leave-active表示插入/更新/移除过程的活动状态,而-enter-leave-to表示插入/更新/移除过程的开始和结束状态。

2. TransitionGroup

TransitionGroup 组件可以将多个元素一起包裹,并在它们插入/更新/移除时应用过渡效果。这个组件的使用方式与 Transition 类似,但是针对列表元素的过渡处理更加方便。以下是一个例子:

vue
<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-activelist-leave-active
  • CSS 样式中的类名也有一些特殊之处,如-enter-from表示插入过程的初始状态,-leave-to表示移除过程结束的状态。

3. KeepAlive

KeepAlive 组件用于缓存组件实例,以便在切换时保持其状态。常用于包含有昂贵的组件,减少不必要的初始化和渲染开销。以下是一个例子:

vue
<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 树中的其他位置,可以用于创建模态框、弹出菜单等组件。以下是一个例子:

vue
<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 组件用于在异步加载组件时显示一个占位符,直到异步操作完成。这个组件通常与异步组件配合使用。以下是一个例子:

vue
<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> 组件结合使用。

vue
<template>
  <RouterView v-slot="{ Component }">
    <Transition mode="out-in">
      <KeepAlive>
        <Suspense>
          <!-- 主要内容 -->
          <component :is="Component"></component>
          <!-- 加载中状态 -->
          <template #fallback>
            正在加载...
          </template>
        </Suspense>
      </KeepAlive>
    </Transition>
  </RouterView>
</template>