Vue3中的組件數(shù)據(jù)懶加載
組件數(shù)據(jù)懶加載-基本使用
目標:通過useIntersectionObserver優(yōu)化新鮮好物和人氣推薦模塊
電商類網(wǎng)站,尤其是首頁,內容有好幾屏,而如果一上來就加載所有屏的數(shù)據(jù),并渲染所有屏的內容會導致首頁加載很慢。
數(shù)據(jù)懶加載:等組件正式進入到可視區(qū)中時,才把組件內部的ajax請求發(fā)起,否則不請求數(shù)據(jù)
(1)優(yōu)化新鮮好物
<script lang="ts" setup>
const { home } = useStore()
const target = ref(null)
const { stop } = useIntersectionObserver(target, ([{ isIntersecting }]) => {
console.log(isIntersecting)
// isIntersecting 是否進入可視區(qū)域,true是進入 false是移出
if (isIntersecting) {
home.getNewList()
stop()
}
})
</script>
<template>
<div class="home-new">
<HomePanel ref="target" title="新鮮好物" sub-title="新鮮出爐 品質靠譜">
</HomePanel>
</div>
</template>
(2)優(yōu)化人氣推薦
<script lang="ts" setup>
const { home } = useStore()
const target = ref(null)
const { stop } = useIntersectionObserver(target, ([{ isIntersecting }]) => {
console.log(isIntersecting)
// isIntersecting 是否進入可視區(qū)域,true是進入 false是移出
if (isIntersecting) {
home.getHotList()
stop()
}
})
</script>
<template>
<HomePanel ref="target" title="人氣推薦" sub-title="人氣爆款 不容錯過">
</HomePanel>
</template>
給ref添加組件類型
參考鏈接:https://staging-cn.vuejs.org/guide/typescript/composition-api.html#typing-component-template-refs
<!-- App.vue -->
<script setup lang="ts">
import MyModal from './MyModal.vue'
const modal = ref<InstanceType<typeof MyModal> | null>(null)
const openModal = () => {
modal.value?.open()
}
</script>
組件數(shù)據(jù)懶加載-封裝
目標:
封裝組件數(shù)據(jù)懶加載可復用的邏輯
分析:
- 首頁中,很多地方都應該使用組件數(shù)據(jù)懶加載這個功能,不管是哪個模塊使用,下面代碼都會重復書寫
- 事實上,唯一可能會隨著業(yè)務使用發(fā)生變化的是 ajax接口的調用
- 其余的部分我們進行重復使用,抽離為可復用邏輯
核心代碼
(1)封裝通用的懶加載數(shù)據(jù)api src/utils/hooks.ts
// 自定義一些通用的compositions api
import { useIntersectionObserver } from '@vueuse/core'
import { ref } from 'vue'
// 封裝通用的數(shù)據(jù)懶加載api
export function useLazyData(apiFn: () => void) {
// 通過 ref 獲得組件實例
const target = ref(null)
const { stop } = useIntersectionObserver(
// target 是觀察的目標dom容器,必須是dom容器,而且是vue3.0方式綁定的dom對象
target,
// isIntersecting 是否進入可視區(qū)域,true是進入 false是移出
// observerElement 被觀察的dom
([{ isIntersecting }]) => {
// 在此處可根據(jù)isIntersecting來判斷,然后做業(yè)務
if (isIntersecting) {
stop()
apiFn()
}
}
)
return target
}
(2)優(yōu)化新鮮好物
<script lang="ts" setup>
const target = useLazyData(() => {
home.getNewList()
})
</script>
<template>
<div class="home-new">
<HomePanel ref="target" title="新鮮好物" sub-title="新鮮出爐 品質靠譜">
</HomePanel>
</div>
</template>
(3)優(yōu)化人氣推薦
<script lang="ts" setup>
const target = useLazyData(() => {
home.getHotList()
})
</script>
<template>
<HomePanel ref="target" title="人氣推薦" sub-title="人氣爆款 不容錯過">
</HomePanel>
</template>
拓展小知識:自定義lazyhook的類型優(yōu)化
export function useLazyApi(apiFn: () => void) {
const target = ref<MaybeElementRef | null>(null)
const {stop} = useIntersectionObserver(target, ([{isIntersecting}]) => {
if (isIntersecting) {
stop()
apiFn()
}
})
return target
}
添加了ref類型提示:MaybeElementRef -> 暴露出去的taget如果賦值類型不對會進行提示

看一下MaybeElementRef到底是什么類型?
declare type MaybeElementRef<T extends MaybeElement = MaybeElement> = MaybeRef<T>;
declare type MaybeElement = HTMLElement | SVGElement | VueInstance | undefined | null;
declare type MaybeRef<T> = T | Ref<T>;
心得:
MaybeElementRef類型的類型為:
- MaybeElement的Ref類型
- 或者直接為MayBeElement類型
首頁主體-滾動加載商品的bug
- 產品區(qū)域需要滾動比較多才能去加載數(shù)據(jù)。
- threshold 容器和可視區(qū)交叉的占比(進入的面積/容器完整面積) 取值,0-1 之間,默認比0大,所以需要滾動較多才能觸發(fā)進入可視區(qū)域事件。 閾值 (進入的面積/容器完整面積)
const { stop } = useIntersectionObserver(
target,
([{ isIntersecting }], observerElement) => {
if (isIntersecting) {
stop()
// 調用API獲取數(shù)據(jù)
apiFn().then(data => {
result.value = data.result
})
}
},
{
threshold: 0
}
)
rElement) => {
if (isIntersecting) {
stop()
// 調用API獲取數(shù)據(jù)
apiFn().then(data => {
result.value = data.result
})
}
},
{
threshold: 0
}
)
總結
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
vue搭建本地JSON靜態(tài)數(shù)據(jù)服務器全過程
這篇文章主要介紹了vue搭建本地JSON靜態(tài)數(shù)據(jù)服務器全過程,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-07-07

