关于 dynamic-components
这是一项面向 Vue 开发者的技能,介绍如何在运行时切换组件,适用于构建标签页或视图界面。内容涵盖组件选择,以及切换时保留组件状态。
主要功能
- 01根据响应式选择切换组件
- 02用组件映射构建标签视图
- 03使用 KeepAlive 保留状态
适用场景
- 01无需路由构建标签页界面
- 02替代嵌套的 v-if/v-else 渲染
- 03切换标签时保留计数器状态
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ patternsdev/ skills --skill dynamic-components安装后在 Claude Code 中输入/dynamic-components确认已加载。
详细介绍
动态组件
目录
动态组件可以通过将 is 属性绑定到保留的 <component> 元素,实现组件间的动态切换。
我们通过一个示例来更好地理解动态组件的工作方式。假设我们有三个独立的组件,分别名为 Home、Feed 和 History,它们只会显示说明当前组件名称的文本。
适用场景
- 需要根据用户交互(例如标签页、视图)渲染不同组件时使用
- 这可以作为多个
v-if/v-else代码块的替代方案,用于有条件地渲染组件
使用说明
- 将
<component>上的is属性绑定到一个引用组件定义的响应式值 - 使用
tabs对象将名称映射到导入的组件定义 - 使用
<KeepAlive>包裹<component>,以便在切换动态组件时保留状态
详情
<template><div class="tab">Home component</div></template>
<template><div class="tab">Feed component</div></template>
<template><div class="tab">History component</div></template>
我们的目标是构建一个显示标签页列表的界面,用户可以点击这些标签页。根据点击的标签页,我们希望动态渲染相应的组件。
在标签页之间切换时,我们希望无需使用路由,即可动态卸载和挂载组件。虽然使用 v-if 和 v-else 等指令有条件地渲染子模板也能实现类似效果,但 Vue 动态组件正适用于这种场景。
在应用的父级 App 组件中,我们可以先导入三个独立组件,以便在模板中使用它们。我们还会创建一个 currentTab 响应式属性,并将其初始值设为 "Home"。
<script setup>
import { ref } from "vue";
import Home from "./components/Home.vue";
import Feed from "./components/Feed.vue";
import History from "./components/History.vue";
const currentTab = ref("Home");
const tabs = {
Home,
Feed,
History,
};
</script>
请注意,我们的 tabs 对象引用的是实际的组件定义,而不只是组件名称。
在 App 组件模板中,我们要为计划显示的每个组件分别渲染一个标签页按钮,共三个。我们会使用 v-for 指令来实现这一点。
<template>
<div class="demo">
<button
v-for="(_, tab) in tabs"
:key="tab"
:class="['tab-button', { active: currentTab === tab }]"
@click="currentTab = tab"
>
{{ tab }}
</button>
</div>
</template>
要动态渲染特定的子组件,我们会将 is 属性绑定到保留的 <component> 元素。is 属性的值应与我们要动态渲染的子组件相对应。
<template>
<div class="demo">
<button
v-for="(_, tab) in tabs"
:key="tab"
:class="['tab-button', { active: currentTab === tab }]"
@click="currentTab = tab"
>
{{ tab }}
</button>
<component :is="tabs[currentTab]" class="tab"></component>
</div>
</template>
<script setup>
import { ref } from "vue";
import Home from "./components/Home.vue";
import Feed from "./components/Feed.vue";
import History from "./components/History.vue";
const currentTab = ref("Home");
const tabs = {
Home,
Feed,
History,
};
</script>
将动态 <component /> 元素放入模板后,子组件便会根据所选标签页动态卸载和挂载。
保留状态
使用动态组件时,保留状态是一个重要的考量因素。默认情况下,组件卸载时,其状态会丢失。不过,Vue 提供了 <KeepAlive> 组件,可以保留动态组件的状态。
要保留动态组件的状态,我们可以使用 <KeepAlive> 组件包裹 <component> 元素。
<template>
<div class="demo">
<KeepAlive>
<component :is="tabs[currentTab]" class="tab"></component>
</KeepAlive>
</div>
</template>
<script setup>
// ...
</script>
使用 <KeepAlive> 组件包裹 <component> 元素后,动态组件卸载时其状态将得到保留。这意味着所有数据或组件状态都会维持不变,组件再次挂载时也会恢复先前的状态。
我们可以更新每个子组件,添加一个简单的递增计数器,来查看这一效果。
<template>
<div class="tab">
Home component
<p>Counter: {{ counter }}</p>
<button @click="incrementCounter">Increment</button>
</div>
</template>
<script setup>
import { ref } from "vue";
const counter = ref(0);
const incrementCounter = () => {
counter.value++;
};
</script>
经过这些更改,即使动态切换组件,每个子组件各自的计数器状态也会得到保留。
使用 <KeepAlive> 组件,我们可以通过保留动态组件的状态,改善其行为,并在标签页切换时提供更流畅的用户体验。