Vue3中的組件數(shù)據(jù)懶加載
組件數(shù)據(jù)懶加載-基本使用
目標(biāo):通過(guò)useIntersectionObserver優(yōu)化新鮮好物和人氣推薦模塊
電商類網(wǎng)站,尤其是首頁(yè),內(nèi)容有好幾屏,而如果一上來(lái)就加載所有屏的數(shù)據(jù),并渲染所有屏的內(nèi)容會(huì)導(dǎo)致首頁(yè)加載很慢。
數(shù)據(jù)懶加載:等組件正式進(jìn)入到可視區(qū)中時(shí),才把組件內(nèi)部的ajax請(qǐng)求發(fā)起,否則不請(qǐng)求數(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 是否進(jìn)入可視區(qū)域,true是進(jìn)入 false是移出 if (isIntersecting) { home.getNewList() stop() } }) </script> <template> <div class="home-new"> <HomePanel ref="target" title="新鮮好物" sub-title="新鮮出爐 品質(zhì)靠譜"> </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 是否進(jìn)入可視區(qū)域,true是進(jìn)入 false是移出 if (isIntersecting) { home.getHotList() stop() } }) </script> <template> <HomePanel ref="target" title="人氣推薦" sub-title="人氣爆款 不容錯(cuò)過(guò)"> </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ù)懶加載-封裝
目標(biāo):
封裝組件數(shù)據(jù)懶加載可復(fù)用的邏輯
分析:
- 首頁(yè)中,很多地方都應(yīng)該使用組件數(shù)據(jù)懶加載這個(gè)功能,不管是哪個(gè)模塊使用,下面代碼都會(huì)重復(fù)書(shū)寫
- 事實(shí)上,唯一可能會(huì)隨著業(yè)務(wù)使用發(fā)生變化的是 ajax接口的調(diào)用
- 其余的部分我們進(jìn)行重復(fù)使用,抽離為可復(fù)用邏輯
核心代碼
(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) { // 通過(guò) ref 獲得組件實(shí)例 const target = ref(null) const { stop } = useIntersectionObserver( // target 是觀察的目標(biāo)dom容器,必須是dom容器,而且是vue3.0方式綁定的dom對(duì)象 target, // isIntersecting 是否進(jìn)入可視區(qū)域,true是進(jìn)入 false是移出 // observerElement 被觀察的dom ([{ isIntersecting }]) => { // 在此處可根據(jù)isIntersecting來(lái)判斷,然后做業(yè)務(wù) 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="新鮮出爐 品質(zhì)靠譜"> </HomePanel> </div> </template>
(3)優(yōu)化人氣推薦
<script lang="ts" setup> const target = useLazyData(() => { home.getHotList() }) </script> <template> <HomePanel ref="target" title="人氣推薦" sub-title="人氣爆款 不容錯(cuò)過(guò)"> </HomePanel> </template>
拓展小知識(shí):自定義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如果賦值類型不對(duì)會(huì)進(jìn)行提示
看一下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類型
首頁(yè)主體-滾動(dòng)加載商品的bug
- 產(chǎn)品區(qū)域需要滾動(dòng)比較多才能去加載數(shù)據(jù)。
- threshold 容器和可視區(qū)交叉的占比(進(jìn)入的面積/容器完整面積) 取值,0-1 之間,默認(rèn)比0大,所以需要滾動(dòng)較多才能觸發(fā)進(jìn)入可視區(qū)域事件。 閾值 (進(jìn)入的面積/容器完整面積)
const { stop } = useIntersectionObserver( target, ([{ isIntersecting }], observerElement) => { if (isIntersecting) { stop() // 調(diào)用API獲取數(shù)據(jù) apiFn().then(data => { result.value = data.result }) } }, { threshold: 0 } ) rElement) => { if (isIntersecting) { stop() // 調(diào)用API獲取數(shù)據(jù) apiFn().then(data => { result.value = data.result }) } }, { threshold: 0 } )
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
vue輕松實(shí)現(xiàn)虛擬滾動(dòng)的示例代碼
移動(dòng)端網(wǎng)頁(yè)的日常開(kāi)發(fā)中,偶爾會(huì)包含一些渲染長(zhǎng)列表的場(chǎng)景,本文主要介紹了vue 虛擬滾動(dòng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-07-07vue時(shí)間戳和時(shí)間的相互轉(zhuǎn)換方式
本文通過(guò)示例代碼介紹了vue時(shí)間戳和時(shí)間的相互轉(zhuǎn)換方式,通過(guò)場(chǎng)景分析介紹了vue3使用組合式api將時(shí)間戳格式轉(zhuǎn)換成時(shí)間格式(2023年09月28日 10:00),感興趣的朋友一起看看吧2023-12-12vue實(shí)現(xiàn)手機(jī)驗(yàn)證碼登錄
這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)手機(jī)驗(yàn)證碼登錄,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11Vue3全局配置Axios并解決跨域請(qǐng)求問(wèn)題示例詳解
axios 是一個(gè)基于promise的HTTP庫(kù),支持promise所有的API,本文給大家介紹Vue3全局配置Axios并解決跨域請(qǐng)求問(wèn)題,內(nèi)容從axios部署開(kāi)始到解決跨域問(wèn)題,感興趣的朋友一起看看吧2023-11-11vue3響應(yīng)式Object代理對(duì)象的讀取示例詳解
這篇文章主要為大家介紹了vue3響應(yīng)式Object代理對(duì)象的讀取示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08vue3響應(yīng)式對(duì)象的api超全實(shí)例詳解
可以把數(shù)據(jù)變成響應(yīng)式api的方法叫做響應(yīng)式api,下面這篇文章主要給大家介紹了關(guān)于vue3響應(yīng)式對(duì)象api的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-05-05vue搭建本地JSON靜態(tài)數(shù)據(jù)服務(wù)器全過(guò)程
這篇文章主要介紹了vue搭建本地JSON靜態(tài)數(shù)據(jù)服務(wù)器全過(guò)程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-07-07