即便通过 Webpack 的按需加载、CDN 静态资源缓存 和 代码分割 等技术来减少首屏的代码体积,首屏加载时的白屏时间(也称为首屏等待时间)仍然可能存在,尤其在网络条件较差或页面内容复杂时,常见的解决方案是使用骨架屏技术,数据加载前的占位动画可以表示内容还在加载中
核心概念和实现思路
- 使用
IntersectionObserver
进行懒加载IntersectionObserver
用来监听目标元素是否进入视区(即视口)。当某个占位元素(如div
或section
)进入视口时,才异步加载对应的组件。这种方式可以避免首屏加载时不必要的资源占用,提升页面加载速度。- 当组件加载完成后,可以根据需求决定是否需要销毁监听器,比如加载完成即销毁,或者离开视区后销毁。
- 异步组件加载
- 在 Vue 中,使用
() => import('component')
来进行异步加载。异步组件的加载是在用户需要时(通常是当组件进入视区时)才会加载,而不是在页面初始加载时。 - 通过这种懒加载方式,我们可以极大提升首屏加载的性能,因为只有用户能看到的组件会优先加载。
- 在 Vue 中,使用
- 骨架屏
- 在真实组件加载前,用骨架屏占位,提供一个与真实组件大小相近的占位元素,让用户感知页面在加载中,避免空白页面的出现。骨架屏可以是简单的 HTML 结构,如
<section />
,并通过 CSS 渲染出类似加载动画的效果。
- 在真实组件加载前,用骨架屏占位,提供一个与真实组件大小相近的占位元素,让用户感知页面在加载中,避免空白页面的出现。骨架屏可以是简单的 HTML 结构,如
- 内存泄漏防止
- 在页面或组件销毁时,必须调用
IntersectionObserver.disconnect()
,防止继续监听无用的元素,避免内存泄漏。
- 在页面或组件销毁时,必须调用
实现步骤
1. 使用 IntersectionObserver
和骨架屏
通过骨架屏占位符和 IntersectionObserver
实现组件懒加载,先监听占位元素,进入视口时再加载真正的组件。 (注意下面的实现是 v-if,也可以用v-show)
示例代码
<template>
<div>
<!-- 占位元素 (骨架屏) -->
<section ref="observerTarget" class="skeleton-screen">
<!-- 真实组件在可视区时才会懒加载 -->
<component v-if="isVisible" :is="lazyComponent" />
</section>
</div>
</template>
<script>
export default {
data() {
return {
isVisible: false, // 组件是否可见
lazyComponent: null // 懒加载的真实组件
};
},
mounted() {
this.createObserver();
},
beforeDestroy() {
// 销毁时取消监听,防止内存泄漏
if (this.observer) {
this.observer.disconnect();
}
},
methods: {
createObserver() {
const observerOptions = {
root: null, // 默认是视口
threshold: 0.1 // 目标元素至少可见 10% 时触发
};
this.observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
// 当目标元素进入可视区时,加载真实组件
this.loadComponent();
// 加载完成后销毁观察器
this.observer.disconnect();
}
});
}, observerOptions);
// 观察占位符骨架屏
this.observer.observe(this.$refs.observerTarget);
},
loadComponent() {
// 使用异步组件加载实际组件
this.lazyComponent = () => import('./LazyLoadedComponent.vue');
this.isVisible = true; // 组件可见
}
}
};
</script>
<style>
.skeleton-screen {
width: 100%;
height: 200px;
background-color: #eee; /* 骨架屏的占位效果 */
}
</style>
要点说明:
- 骨架屏:
<section ref="observerTarget" class="skeleton-screen">
用作骨架屏,占位在实际组件加载之前。 IntersectionObserver
:通过IntersectionObserver
监听目标元素,当元素进入视区时加载真实组件并销毁观察器。- 异步组件加载:
this.lazyComponent = () => import('./LazyLoadedComponent.vue');
在实际需要时才加载组件。
注意点
- 内存管理:一定要在组件销毁时调用
disconnect()
释放IntersectionObserver
,否则可能导致内存泄漏。 - 异步组件加载的性能:异步组件加载可以显著减少首屏资源的消耗,但如果过度使用,可能会增加页面的延迟。确保只在必要时使用懒加载。
参考
https://blog.csdn.net/qq_42002794/article/details/124125526
Vue首屏性能优化组件 - Blog (touchczy.top)
https://www.ruanyifeng.com/blog/2016/11/intersectionobserver_api.html
.top/zh-cn/Vue/Vue首屏性能优化组件.html#描述)
https://www.ruanyifeng.com/blog/2016/11/intersectionobserver_api.html
标签:骨架,占位,组件,IntersectionObserver,首屏,优化,加载 From: https://blog.csdn.net/youxinm24/article/details/142645444