一、动态组件
可使用keep-alive加载组件
注意:使用markRaw来避免出现响应式组件消耗性能
<template>
<div class="home">
<div class="tabBox">
<div :class="['tab',index==tabActive? 'active':'']" v-for="(el,index) in tabList" :key="index" @click="changeTab(index)">
{{el.name}}
</div>
</div>
<div class="tabContext">
<component :is="currentComponent.com"></component>
</div>
</div>
</template>
<script setup>
import A from '../components/A.vue'
import B from '../components/B.vue'
import C from '../components/C.vue'
//tab的渲染数据
let tabList=reactive([
{name:"tab1",com:markRaw(A)},
{name:"tab2",com:markRaw(B)},
{name:"tab3",com:markRaw(C)}
])
//tab选中的索引
let tabActive=ref(0)
//点击到tab要切换的组件
let currentComponent= reactive({
com:tabList[0].com
})
//点击tab切换组件
const changeTab=(index)=>{
tabActive.value=index
currentComponent.com=tabList[index].com
}
</script>
<style lang="scss">
.home{
font-size: 32px;
line-height: 50px;
.tabBox{
width: 100%;;
display: flex;
align-items: center;
border: 1px solid red;
.tab{
font-size: 26px;
flex: 1;
background: red;
text-align: center;
cursor: pointer;
}
.active{
font-size: 26px;
color: #fff;
}
}
.tabContext{
padding: 20px 0;
width: 100%;
border: 1px solid red;
}
}
</style>
二、异步组件
在大型项目中,我们可能需要拆分应用为更小的块,并仅在需要时再从服务器加载相关组件。Vue 提供了 defineAsyncComponent 方法来实现此功能
优点:提升性能
vueuse: VueUse | VueUse-dome
1.1场景1
组件按需引入 :当用户滑动到了具体之间的位置再去加载该组件(实现组件懒加载,到他了再去加载节省性能)
使用Usage :@vueuse/core这个包
npm i @vueuse/core -S
父
<template>
<div class="home">
<A></A>
<B></B>
<div ref="target">
<C v-if="targetIsVisible"></C>
</div>
</div>
</template>
<script setup>
import A from '../components/A.vue'
import B from '../components/B.vue'
// import C from '../components/C.vue'
import { useIntersectionObserver } from '@vueuse/core'
const C = defineAsyncComponent(() =>
import('../components/C.vue')
)
const target = ref(null)
const targetIsVisible = ref(false)
const { stop } = useIntersectionObserver(
target,
([{ isIntersecting }]) => {
console.log(isIntersecting,'----');
if(isIntersecting) targetIsVisible.value = isIntersecting
}
)
</script>
<style lang="scss">
.home{
font-size: 32px;
line-height: 50px;
}
</style>
子
<template>
<div class="C">
<h1>C组件</h1>
<img src="../assets/vue.svg" alt="">
</div>
</template>
<script setup>
</script>
<style lang="scss">
.C{
font-size: 26px;
height: 1500px;
background: green;
}
</style>
1.2场景2
异步请求的时候,可以做加载中处理
home
<template>
<div class="home">
<Suspense>
<template #fallback>
加载中...
</template>
<template #default>
<A></A>
</template>
</Suspense>
<B></B>
</div>
</template>
<script setup>
import B from '../components/B.vue'
import {
useIntersectionObserver
} from '@vueuse/core'
const A = defineAsyncComponent(() =>
import('../components/A.vue')
)
</script>
<style lang="scss">
.home {
font-size: 32px;
line-height: 50px;
}
</style>
A.vue
<template>
<div class="A">
<h1>A组件</h1>
{{list}}
</div>
</template>
<script setup>
let list = ref([])
//当前组件实例
let _this =getCurrentInstance().appContext.config.globalProperties
//获取list数据
const getList=async ()=>{
let res = await _this.$getJson('./static/json/A.json')
list.value = res.data.list
}
await getList()
onMounted(async () => {
// await getList()
})
</script>
<style lang="scss">
.A {
font-size: 26px;
}
</style>
1.3场景3
#通过defineAsyncComponent分包处理:对组件或者页面进行分包处理
这里A和C组件使用了defineAsyncComponent异步组件所以分包打包了
<template>
<div class="home">
<Suspense>
<template #fallback>
加载中...
</template>
<template #default>
<A></A>
</template>
</Suspense>
<B></B>
<div ref="target">
<C v-if="targetIsVisible"></C>
</div>
</div>
</template>
<script setup>
import B from '../components/B.vue'
import {
useIntersectionObserver
} from '@vueuse/core'
const A = defineAsyncComponent(() =>
import('../components/A.vue')
)
const C = defineAsyncComponent(() =>
import('../components/C.vue')
)
const target = ref(null)
let targetIsVisible = ref(false)
const {
stop
} = useIntersectionObserver(
target,
([{
isIntersecting
}]) => {
console.log(isIntersecting, '----');
if (isIntersecting) targetIsVisible.value = isIntersecting
}
)
</script>
<style lang="scss">
.home {
font-size: 32px;
line-height: 50px;
}
</style>