Nuxt.js项目如何实现滚动时预加载指定数量图片,减少多余服务器请求
实现方案(纯原生JS实现,Nuxt全版本兼容)
你需要的功能本质是可视区加载+范围预加载,所有图片URL预先存在前端即可,不会额外发起分页接口请求,仅控制图片资源的下载时机,完全不会增加服务器接口压力。
核心逻辑
你已经完成了Intersection Observer的基础配置和自定义图片组件封装,只需要补充加载范围控制逻辑即可:
- 所有图片初始不赋值真实
src,用data-src自定义属性存储真实地址,默认展示占位图 - 维护一个
maxLoadedIndex变量,记录当前已经加载到的图片最大下标 - 当某张图片进入可视区时,以该图片下标为起点,往后顺延5个下标作为本次加载的终点
- 仅加载该范围内还未加载的图片,更新
maxLoadedIndex,避免重复处理
具体代码实现
1. 自定义图片组件
<template> <img class="lazy-img" :src="placeholder" :data-src="realSrc" :data-index="imgIndex" alt="" /> </template> <script setup> const props = defineProps({ realSrc: { type: String, required: true }, imgIndex: { type: Number, required: true }, placeholder: { type: String, default: '/static/default-placeholder.png' } // 替换为你的占位图地址 }) </script> <style scoped> .lazy-img { transition: opacity 0.3s ease; opacity: 0.4; } /* 加载完成后显示正常透明度 */ .lazy-img:not([data-src]) { opacity: 1; } </style>
2. 页面加载控制逻辑
<template> <div class="img-container"> <LazyImg v-for="(url, idx) in allImgList" :key="idx" :real-src="url" :img-index="idx" /> </div> </template> <script setup> import LazyImg from './LazyImg.vue' // 提前把所有图片URL存在前端,不需要滚动请求接口 const allImgList = ref([ // 这里放入你20张图片的真实URL ]) // 已加载的最大图片下标 const maxLoadedIndex = ref(-1) // 预加载后续图片数量,可自行调整 const PRELOAD_NUM = 5 let observer = null onMounted(() => { observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { // 拿到当前进入可视区的图片下标 const currentIdx = Number(entry.target.dataset.index) // 计算本次需要加载到的最大下标,不超过数组总长度 const targetIdx = Math.min(currentIdx + PRELOAD_NUM, allImgList.value.length - 1) // 仅加载未处理过的图片 if (targetIdx > maxLoadedIndex.value) { for (let i = maxLoadedIndex.value + 1; i <= targetIdx; i++) { const imgEl = document.querySelector(`.lazy-img[data-index="${i}"]`) if (imgEl?.dataset.src) { // 赋值src触发图片资源加载 imgEl.src = imgEl.dataset.src // 移除属性避免重复处理 delete imgEl.dataset.src } } maxLoadedIndex.value = targetIdx } // 全部图片加载完成后断开监听,释放内存 if (maxLoadedIndex.value >= allImgList.value.length - 1) { observer.disconnect() } } }) }, { threshold: 0.1 }) // 监听所有图片元素 document.querySelectorAll('.lazy-img').forEach(el => observer.observe(el)) }) onUnmounted(() => { observer?.disconnect() }) </script>
适配优化
如果是Nuxt3项目,可以直接用内置的useIntersectionObserver组合式API替换原生Intersection Observer的初始化逻辑,代码会更简洁,无需手动处理监听销毁逻辑。
内容的提问来源于stack exchange,提问作者StarPass
相关产品推荐
相关产品推荐

