图片懒加载

一、原生懒加载:最简方案

现代浏览器已广泛支持 loading="lazy" 属性,只需在 <img> 标签中添加即可自动实现懒加载。

  • 优势:无需编写 JavaScript,浏览器自动处理加载时机,兼容性覆盖 93.7% 的用户。
  • 使用示例
    <img src="placeholder.jpg" loading="lazy" data-src="real-image.jpg" alt="示例图片" width="300" height="200">
    
  • 注意事项
    • 设置宽高:必须指定 width 和 height,避免布局抖动(CLS)。
    • 首屏避免使用:首屏关键图片(如 LCP 元素)禁用此属性,防止影响加载优先级。

二、使用第三方库 vue-lazyload(推荐)

vue-lazyload 是 Vue 生态中最常用的图片懒加载库,支持 Vue2 和 Vue3,提供了丰富的配置(如占位图、加载失败处理、过渡效果等)。

1. 安装依赖
# Vue2 项目
npm install vue-lazyload@1.3.3  # 1.x 版本适配 Vue2
# 或
yarn add vue-lazyload@1.3.3

# Vue3 项目
npm install vue-lazyload@3  # 3.x 版本适配 Vue3
# 或
yarn add vue-lazyload@3
2. 全局配置(main.js)
// Vue2 示例
import Vue from 'vue'
import App from './App.vue'
import VueLazyload from 'vue-lazyload'

// 配置懒加载
Vue.use(VueLazyload, {
  preLoad: 1.3, // 预加载高度比例(1.3 表示提前加载视口 1.3 倍高度的图片)
  error: require('@/assets/error.png'), // 加载失败时显示的图片
  loading: require('@/assets/loading.gif'), // 加载中显示的占位图
  attempt: 1, // 加载失败重试次数
  throttleWait: 200 // 节流等待时间(毫秒)
})

new Vue({
  render: h => h(App)
}).$mount('#app')
3. 组件中使用

在模板中,将 v-bind:src 替换为 v-lazy 指令:

<template>
  <div class="image-list">
    <!-- 普通图片 -->
    <img 
      v-lazy="imageUrl" 
      alt="示例图片"
      class="lazy-img"
    >

    <!-- 列表中的图片(如长列表) -->
    <div v-for="(item, index) in imageList" :key="index">
      <img 
        v-lazy="item.url" 
        :alt="item.alt"
        v-lazy:error="item.errorUrl"  <!-- 单独设置该图片的失败图 -->
        v-lazy:loading="item.loadingUrl"  <!-- 单独设置该图片的占位图 -->
      >
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      imageUrl: 'https://picsum.photos/800/600', // 实际图片地址
      imageList: [
        { url: 'https://picsum.photos/800/601', alt: '图片1' },
        { url: 'https://picsum.photos/800/602', alt: '图片2' }
      ]
    }
  }
}
</script>

三、原生 API 实现(不依赖第三方库)

利用浏览器原生的 IntersectionObserver API 监听图片是否进入视口,手动控制图片加载。适用于对项目体积有严格要求的场景。

1. 实现原理
  • 初始时,图片的 src 或 srcset 设为占位图(或不设置),将真实地址存放在 data-src(自定义属性)中。
  • 通过 IntersectionObserver 监听图片元素,当元素进入视口时,将 data-src 的值赋给 src,触发图片加载。
2. Vue 自定义指令实现

创建一个全局自定义指令 v-lazy,封装懒加载逻辑:

// Vue2 示例(main.js)
import Vue from 'vue'
import App from './App.vue'

// 注册全局懒加载指令
Vue.directive('lazy', {
  // 指令绑定到元素时触发
  bind(el, binding) {
    // 存储真实图片地址
    el.dataset.src = binding.value

    // 初始显示占位图(可选)
    el.src = require('@/assets/placeholder.png')
  },
  // 元素插入 DOM 时触发
  inserted(el) {
    // 创建观察器实例
    const observer = new IntersectionObserver((entries) => {
      entries.forEach(entry => {
        // 元素进入视口
        if (entry.isIntersecting) {
          // 获取真实图片地址
          const src = el.dataset.src
          if (src) {
            // 设置 src 触发加载
            el.src = src
            // 加载完成后停止观察
            observer.unobserve(el)
          }
        }
      })
    }, {
      rootMargin: '100px 0px' // 提前 100px 加载
    })

    // 开始观察目标元素
    observer.observe(el)
  }
})

new Vue({
  render: h => h(App)
}).$mount('#app')
3. 组件中使用自定义指令
<template>
  <div class="image-list">
    <!-- 使用自定义 v-lazy 指令 -->
    <img 
      v-lazy="imageUrl" 
      alt="原生懒加载示例"
    >

    <!-- 列表图片 -->
    <img 
      v-for="(item, index) in imageList" 
      :key="index"
      v-lazy="item.url" 
      :alt="item.alt"
    >
  </div>
</template>

<script>
export default {
  data() {
    return {
      imageUrl: 'https://picsum.photos/800/600',
      imageList: [
        { url: 'https://picsum.photos/800/601', alt: '图片1' },
        { url: 'https://picsum.photos/800/602', alt: '图片2' }
      ]
    }
  }
}
</script>

总结

图片懒加载是优化长列表或图片密集型页面的核心技术。实际开发中,推荐使用 vue-lazyload 快速实现,其丰富的配置能满足大多数需求;若项目对依赖体积有严格限制,可基于 IntersectionObserver 实现自定义懒加载指令。

    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值