当一个页面需要加载较多个组件时,并且组件自身又比较复杂。如果一次性加载,可能等待时间较长,体验不好。
一种解决办法:分批次的来渲染子组件。
通过 requestAnimationFrame(callback)
实现,同时能够控制按照指定顺序来渲染。
简单理解为:浏览器会按照一定的频率来重绘页面,大概 60次/s。每次重绘前都会执行 callback
函数。这样的话,我们可以在每次重绘前都只渲染一个组件,来实现组件的延迟加载。
示例代码:
通过 mixin
来实现。大致逻辑:
callback
时自增,重绘次数达到最大则结束 requestAnimationFrame
的执行。v-if="deferItem(5)"
表示浏览器第5次重绘时渲染该组件。export default function defer(maxFrameCount) {
return {
data() {
return {
frameCount: 0,
};
},
mounted() {
const refreshFrame = () => {
requestAnimationFrame(() => {
this.frameCount++;
if (this.frameCount < maxFrameCount) {
refreshFrame();
}
});
};
refreshFrame();
},
methods: {
deferItem(showFrameCount) {
return this.frameCount >= showFrameCount;
},
},
};
}
子组件内部有 20000 个元素需要渲染,来模拟复杂的组件。
<template>
<div class="container">
<div v-for="n in 20000" class="item"></div>
</div>
</template>
<script></script>
<style scoped>
.container {
display: flex;
flex-wrap: wrap;
align-items: center;
width: 300px;
height: 300px;
}
.item {
width: 5px;
height: 5px;
background-color: #eee;
margin: 0.1em;
}
</style>
模拟渲染 25 个复杂子组件。
<template>
<div class="container">
<div v-for="n in 25" :key="n" class="wrapper">
<HeavyComp v-if="deferItem(n)" />
</div>
</div>
</template>
<script>
import HeavyComp from "./components/HeavyComp.vue";
import defer from "./mixins/defer";
export default {
components: {
HeavyComp,
},
mixins: [defer(25)],
};
</script>
<style scoped>
.container {
display: flex;
flex-wrap: wrap;
}
.wrapper {
border: 1px solid salmon;
}
</style>
以上。