news 2026/6/3 23:41:20

Vue—— Vue3 懒加载与预加载策略

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Vue—— Vue3 懒加载与预加载策略

背景问题:
需要优化页面加载性能。

方案思考:
使用懒加载和预加载策略来平衡性能和用户体验。

具体实现:
图片懒加载指令:

// directives/lazy-image.jsexportdefault{mounted(el,binding){// 创建 Intersection Observerconstobserver=newIntersectionObserver((entries)=>{entries.forEach(entry=>{if(entry.isIntersecting){// 图片进入视口,加载真实图片constimg=newImage()img.onload=()=>{el.src=binding.value el.classList.remove('lazy-img--loading')el.classList.add('lazy-img--loaded')observer.unobserve(el)}img.src=binding.value// 添加加载状态样式el.classList.add('lazy-img--loading')el.src='data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgZmlsbD0iI2NjYyIvPjwvc3ZnPg=='// 占位图}})})observer.observe(el)},updated(el,binding){// 当绑定值变化时更新if(binding.value!==binding.oldValue){el.src='data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgZmlsbD0iI2NjYyIvPjwvc3ZnPg=='el.classList.remove('lazy-img--loaded')constobserver=newIntersectionObserver((entries)=>{entries.forEach(entry=>{if(entry.isIntersecting){constimg=newImage()img.onload=()=>{el.src=binding.value el.classList.remove('lazy-img--loading')el.classList.add('lazy-img--loaded')observer.unobserve(el)}img.src=binding.value el.classList.add('lazy-img--loading')}})})observer.observe(el)}}}

组件懒加载:

<!-- components/LazyComponent.vue --> <template> <div class="lazy-component"> <div v-if="loading" class="loading-placeholder"> <el-skeleton :rows="5" /> </div> <component v-else :is="dynamicComponent" v-bind="componentProps" /> </div> </template> <script setup> import { ref, defineAsyncComponent } from 'vue' const props = defineProps({ componentPath: { type: String, required: true }, componentProps: { type: Object, default: () => ({}) } }) const loading = ref(true) const dynamicComponent = ref(null) // 动态加载组件 const loadComponent = async () => { try { // 使用 defineAsyncComponent 进行懒加载 dynamicComponent.value = defineAsyncComponent({ loader: () => import(`@/components/${props.componentPath}.vue`), loadingComponent: null, // 我们自己处理加载状态 errorComponent: null, // 我们自己处理错误 delay: 200, // 延迟显示加载状态 timeout: 3000 // 超时时间 }) } catch (error) { console.error('组件加载失败:', error) } finally { loading.value = false } } loadComponent() </script> <style scoped> .loading-placeholder { padding: 20px; } </style>

预加载策略:

// utils/prefetch.js// 预加载工具类exportclassPrefetchUtil{constructor(){this.prefetchedResources=newSet()}// 预加载脚本asyncprefetchScript(src){if(this.prefetchedResources.has(src)){return}returnnewPromise((resolve,reject)=>{constlink=document.createElement('link')link.rel='prefetch'link.href=src link.onload=resolve link.onerror=reject document.head.appendChild(link)this.prefetchedResources.add(src)})}// 预加载组件asyncprefetchComponent(componentPath){if(this.prefetchedResources.has(componentPath)){return}try{awaitimport(`@/components/${componentPath}.vue`)this.prefetchedResources.add(componentPath)}catch(error){console.error('预加载组件失败:',error)}}// 预加载路由asyncprefetchRoute(routeName){// 这里可以根据路由名称预加载对应组件constrouteModule=awaitimport(`@/views/${routeName}.vue`)returnrouteModule}// 根据用户行为预测预加载predictAndPrefetch(routes){// 基于用户历史行为或路由关系预测可能访问的页面routes.forEach(route=>{setTimeout(()=>{this.prefetchRoute(route)},2000)// 延迟预加载,避免影响当前页面性能})}// 清除预加载缓存clearCache(){this.prefetchedResources.clear()}}// 创建全局预加载实例exportconstprefetchUtil=newPrefetchUtil()

虚拟滚动实现:

<!-- components/VirtualList.vue --> <template> <div ref="containerRef" class="virtual-list" :style="{ height: containerHeight + 'px' }" @scroll="handleScroll" > <div :style="{ height: totalHeight + 'px' }" class="virtual-list__spacer"> <div v-for="item in visibleItems" :key="item.id" :style="{ height: itemHeight + 'px', transform: `translateY(${item.index * itemHeight}px)` }" class="virtual-list__item" > <slot :item="item" :index="item.index" /> </div> </div> </div> </template> <script setup> import { ref, computed, onMounted, onUnmounted } from 'vue' const props = defineProps({ items: { type: Array, required: true }, itemHeight: { type: Number, default: 50 }, containerHeight: { type: Number, default: 400 } }) const containerRef = ref(null) const scrollTop = ref(0) // 计算可见项 const visibleRange = computed(() => { const startIndex = Math.floor(scrollTop.value / props.itemHeight) const visibleCount = Math.ceil(props.containerHeight / props.itemHeight) const endIndex = Math.min(startIndex + visibleCount + 5, props.items.length) // 多渲染几个以防万一 return { start: Math.max(0, startIndex), end: endIndex } }) // 可见项数据 const visibleItems = computed(() => { return props.items .slice(visibleRange.value.start, visibleRange.value.end) .map((item, index) => ({ ...item, index: visibleRange.value.start + index })) }) // 总高度 const totalHeight = computed(() => props.items.length * props.itemHeight) // 处理滚动 const handleScroll = () => { scrollTop.value = containerRef.value.scrollTop } onMounted(() => { scrollTop.value = containerRef.value.scrollTop }) </script> <style scoped> .virtual-list { overflow-y: auto; position: relative; } .virtual-list__spacer { position: relative; width: 100%; } .virtual-list__item { position: absolute; left: 0; right: 0; display: flex; align-items: center; padding: 0 16px; border-bottom: 1px solid #eee; } </style>
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/1 12:26:50

交通仿真软件:VISSIM_(1).VISSIM软件概述

VISSIM软件概述 1. VISSIM软件简介 VISSIM&#xff08;VIenna Simulation Software for Intersection, Merging, and other road systems&#xff09;是一款由PTV Group开发的微观交通仿真软件。它主要用于城市交通网络的建模和仿真&#xff0c;能够详细模拟交通流的动态特性&a…

作者头像 李华
网站建设 2026/6/3 0:33:12

Qwen CLI完全指南:从零开始掌握通义千问命令行工具

Qwen CLI完全指南&#xff1a;从零开始掌握通义千问命令行工具 【免费下载链接】Qwen The official repo of Qwen (通义千问) chat & pretrained large language model proposed by Alibaba Cloud. 项目地址: https://gitcode.com/GitHub_Trending/qw/Qwen 通义千问…

作者头像 李华
网站建设 2026/5/31 13:31:46

OptiScaler终极指南:解锁游戏性能优化的完整教程

OptiScaler终极指南&#xff1a;解锁游戏性能优化的完整教程 【免费下载链接】OptiScaler DLSS replacement for AMD/Intel/Nvidia cards with multiple upscalers (XeSS/FSR2/DLSS) 项目地址: https://gitcode.com/GitHub_Trending/op/OptiScaler 还在为游戏画面卡顿、…

作者头像 李华
网站建设 2026/5/21 11:31:02

Qwen2.5-7B部署指南:监控告警系统集成方案

Qwen2.5-7B部署指南&#xff1a;监控告警系统集成方案 1. 引言 1.1 业务场景描述 随着大语言模型在企业级应用中的广泛落地&#xff0c;如何将高性能的LLM稳定、安全地部署到生产环境&#xff0c;并实现可观测性与自动化运维&#xff0c;已成为AI工程化的重要课题。本文聚焦…

作者头像 李华