动态组件指的是:同一个页面使用多个组件,且可以动态切换。
使用场景:动态组件多用于 tabs标签页
1、在页面中使用 component 标签,然后使用 :is=“组件名”
import A from './components/A.vue'
import B from './components/B.vue'
import C from './components/C.vue'
<component :is="curCom"></component>
const curCom = ref(shallowRef(A))
由于 component 在Vue3 setup 是通过组件实例切换的,如果直接用 reactive 或者 ref 直接包裹组件的话,会使得组件信息也会被劫持,但是其实这些劫持是没有必要的,会造成性能上的浪费,此时Vue会给出警告,正确的方式是:使用 shallowRef 和 markRaw 搭配。
完整代码
A.vue
<template>
<div class="a-box">我是A组件</div>
</template>
<script setup lang="ts"></script>
<style scoped lang="scss">
.a-box {
width: 400px;
height: 200px;
border: 1px solid #ccc;
display: flex;
justify-content: center;
align-items: center;
}
</style>
B.vue
<template>
<div class="b-box">我是B组件</div>
</template>
<script setup lang="ts"></script>
<style scoped lang="scss">
.b-box {
width: 400px;
height: 200px;
border: 1px solid #ccc;
display: flex;
justify-content: center;
align-items: center;
}
</style>
C.vue
<template>
<div class="c-box">我是C组件</div>
</template>
<script setup lang="ts"></script>
<style scoped lang="scss">
.c-box {
width: 400px;
height: 200px;
border: 1px solid #ccc;
display: flex;
justify-content: center;
align-items: center;
}
</style>
App.vue
<template>
<div class="tabs">
<div
@click="switchCom(item, index)"
:class="[active == index ? 'active' : '']"
class="tabs-item"
v-for="(item, index) in data"
>
<div>{{ item.name }}</div>
</div>
</div>
<component :is="curCom"></component>
</template>
<script setup lang="ts">
import { markRaw, reactive, ref, shallowRef } from 'vue'
import A from './components/A.vue'
import B from './components/B.vue'
import C from './components/C.vue'
const curCom = ref(shallowRef(A))
const active = ref(0)
const data = reactive([
{
name: 'A组件',
com: markRaw(A),
},
{
name: 'B组件',
com: markRaw(B),
},
{
name: 'C组件',
com: markRaw(C),
},
])
const switchCom = (item: any, index: number) => {
curCom.value = item.com
active.value = index
}
</script>
<style lang="scss">
.tabs {
display: flex;
.tabs-item {
padding: 5px;
border: 1px solid #ccc;
margin: 5px;
}
.active {
background: #6690ec;
}
}
</style>
2、使用 v-if 或 v-show 来动态渲染组件
import A from './components/A.vue'
import B from './components/B.vue'
import C from './components/C.vue'
<A v-if="curCom == 'A'"></A>
<B v-if="curCom == 'B'"></B>
<C v-if="curCom == 'C'"></C>
const curCom = ref('A')
完整代码
<template>
<div class="tabs">
<div
@click="switchCom(item)"
:class="[curCom == item.com ? 'active' : '']"
class="tabs-item"
v-for="item in data"
>
<div>{{ item.name }}</div>
</div>
</div>
<A v-if="curCom == 'A'"></A>
<B v-if="curCom == 'B'"></B>
<C v-if="curCom == 'C'"></C>
</template>
<script setup lang="ts">
import { reactive, ref } from 'vue'
import A from './components/A.vue'
import B from './components/B.vue'
import C from './components/C.vue'
const curCom = ref('A')
const data = reactive([
{
name: 'A组件',
com: 'A',
},
{
name: 'B组件',
com: 'B',
},
{
name: 'C组件',
com: 'C',
},
])
const switchCom = (item: any) => {
curCom.value = item.com
}
</script>
<style lang="scss">
.tabs {
display: flex;
.tabs-item {
padding: 5px;
border: 1px solid #ccc;
margin: 5px;
}
.active {
background: #6690ec;
}
}
</style>