You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Nuxt.js项目如何实现滚动时预加载指定数量图片,减少多余服务器请求

实现方案(纯原生JS实现,Nuxt全版本兼容)

你需要的功能本质是可视区加载+范围预加载,所有图片URL预先存在前端即可,不会额外发起分页接口请求,仅控制图片资源的下载时机,完全不会增加服务器接口压力。

核心逻辑

你已经完成了Intersection Observer的基础配置和自定义图片组件封装,只需要补充加载范围控制逻辑即可:

  1. 所有图片初始不赋值真实src,用data-src自定义属性存储真实地址,默认展示占位图
  2. 维护一个maxLoadedIndex变量,记录当前已经加载到的图片最大下标
  3. 当某张图片进入可视区时,以该图片下标为起点,往后顺延5个下标作为本次加载的终点
  4. 仅加载该范围内还未加载的图片,更新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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 12:06:01