vue__动态和异步组件

一、动态组件

可使用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>

  • 8
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值