动态组件
有些场景会需要在两个组件间来回切换,比如 Tab 界面:
<script setup>
import Home from "./Home.vue";
import Posts from "./Posts.vue";
import Archive from "./Archive.vue";
import { ref } from "vue";
const currentTab = ref("Home");
const tabs = {
Home,
Posts,
Archive,
};
</script>
<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>
<style>
.demo {
font-family: sans-serif;
border: 1px solid #eee;
border-radius: 2px;
padding: 20px 30px;
margin-top: 1em;
margin-bottom: 40px;
user-select: none;
overflow-x: auto;
}
.tab-button {
padding: 6px 10px;
border-top-left-radius: 3px;
border-top-right-radius: 3px;
border: 1px solid #ccc;
cursor: pointer;
background: #f0f0f0;
margin-bottom: -1px;
margin-right: -1px;
}
.tab-button:hover {
background: #e0e0e0;
}
.tab-button.active {
background: #e0e0e0;
}
.tab {
border: 1px solid #ccc;
padding: 10px;
}
</style>
<template>
<div class="tab">Home component</div>
</template>
<template>
<div class="tab">Posts component</div>
</template>
<template>
<div class="tab">Posts component</div>
</template>
上面的例子是通过 Vue 的 <component>
元素和特殊的 is attribute 实现的:
<!-- currentTab 改变时组件也改变 -->
<component :is="tabs[currentTab]"></component>
在上面的例子中,被传给 :is
的值可以是以下几种:
- 被注册的组件名
- 导入的组件对象
你也可以使用 is
attribute 来创建一般的 HTML 元素。
当使用 <component :is="...">
来在多个组件间作切换时,被切换掉的组件会被卸载。我们可以通过 <KeepAlive>
组件 强制被切换掉的组件仍然保持“存活”的状态。
案例
需求:完成一个注册功能页面,2 个按钮切换,一个填写注册信息,一个填写用户简介信息
效果如下:
准备被切换的 -
UserName.vue
/UserInfo.vue
2 个组件引入到
UseDynamic.vue
注册准备变量来承载要显示的"组件名"
设置挂载点
<component>
, 使用 is 属性来设置要显示哪个组件点击按钮 – 修改
comName
变量里的"组件名"
<script setup>
// 目标:动态组件 - 切换组件显示
// 场景:同一个挂载点要切换 不同组件 显示
// 1. 创建要被切换的组件 - 标签 + 样式
// 2. 引入到要展示的 vue 文件内,注册
// 3. 变量 - 承载要显示的组件名
// 4. 设置挂载点<component :is="变量"></component>
// 5. 点击按钮 - 切换 comName 的值为要显示的组件名
import UserName from "./components/UserName.vue";
import UserInfo from "./components/UserInfo.vue";
import { ref } from "vue";
const com = ref(UserName);
</script>
<template>
<div>
<button @click="com = UserName">账号密码填写</button>
<button @click="com = UserInfo">个人信息填写</button>
<p>下面显示注册组件 - 动态切换:</p>
<div style="border: 1px solid red;">
<component :is="com"></component>
</div>
</div>
</template>
<style scoped></style>
总结:vue 内置 component 组件,配合 is 属性,设置要显示的组件名字
组件缓存
组件切换会导致组件被频繁销毁和重新创建,性能不高。使用 Vue 内置的 keep-alive 组件,可以让包裹的组件保存在内存中不被销毁
演示 1: 可以先给 UserName.vue 和 UserInfo.vue 注册 created 和 destroyed 生命周期事件,观察创建和销毁过程
演示 2: 使用 keep-alive 内置的 vue 组件,让动态组件缓存而不是销毁
语法:
Vue 内置的 keep-alive 组件 包起来要频繁切换的组件
<template>
<div style="border: 1px solid red;">
<!-- Vue 内置 keep-alive 组件,把包起来的组件缓存起来 -->
<keep-alive>
<component :is="com"></component>
</keep-alive>
</div>
</template>
补充生命周期:
- activated - 激活
- deactivated - 失去激活状态
总结:keep-alive 可以提高组件的性能,内部包裹的标签不会被销毁和重新创建,触发激活和非激活的生命周期方法
激活和非激活
目标:被缓存的组件不再创建和销毁,而是激活和非激活
补充 2 个钩子方法名:
onActivated – 激活时触发
onDeactivated – 失去激活状态触发