如果首屏加载的内容组件比较厚重或者数量大,那么第一次加载也会停顿很久。
可以通过控制台的Performence来观察render和loading的大致时间
优化的思路: 想让首屏页面的组件或者比较需要提前让用户看到的内容模块 优先放在第一帧来加载
加载时机:如果当前帧数时间大于 该模块的设定指定加载帧数时间,就让模块去加载
案例:目前通过大组件的案例来实践
<template>
<div class="container">
<div v-for="n in 100" :key="n"> //这里通过重复的大组件来实现效果
<heavyComp v-if="defer(n)"></heavyComp> //当 defer 返回 true 代表组件加载的时机
</div>
</div>
</template>
<script setup>
import heavyComp from '@/components/heavyComp.vue'
import {useDefer} from '@/utils/useDefer'
const defer = useDefer(100)
</script>
<style lang="scss" scoped>
.container{
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-gap: 1em;
}
</style>
创建一个useDefer 的hook函数
import { onUnmounted, ref, getCurrentInstance } from "vue"
export function useDefer(maxCount = 100){
const frameCount = ref(0) //定义一个计数器变量,用于控制 defer 动画的次数,当为 0
const instance = getCurrentInstance() //获取当前实例对象,可以是 vm 对象或自定义实例。这个对象包含了一些方法,用于控制动画。 (请参见该实例的方法) 创建 defer 动画时,将 frameCount.value 加 1 并将其写入到动画定时器中,每当该变量的值大于等于 1 时,将重新开始定时器,以便在定时器中计数。
let rafId;
function updateFrameCount() {
rafId = requestAnimationFrame(() => { //requestAnimationFrame来设置当前已经渲染到哪一帧了
frameCount.value++
if(frameCount.value >= maxCount){
cancelAnimationFrame(rafId)
return;
}
updateFrameCount()
})
}
updateFrameCount();
onUnmounted(() => {
cancelAnimationFrame(rafId)
}, instance)
return function defer(n){
return frameCount.value >= n
}
}