图片懒加载,看这一篇就够了 实现by原生+Vue2+Vue3

图片懒加载



一、为什么需要懒加载

随着互联网技术发展,各类网站基本都已配载大量丰富多彩的图片,但如果寄希望于把所有图片一次性加载完成,那对于用户体验来说将是灾难性的。

目前业界较为推崇的方法是懒加载,简单来说,就是设置在用户可视区之外的图片默认不加载,当图片随着用户的滚动操作进入了可显范围时,则加载显示图片。

话不多说,直接上代码。

二、JavaScript原生实现

使用 intersectionObserver()

const images = document.querySelectorAll('img') // 获取所有图片标签元素

const observer = new IntersectionObserver(entries => {
    entries.forEach(entry => {
        // 判断当前元素是否可见
        if (entry.isIntersecting) {
            // 创建一个自定义属性data-src存放真正要显示的图片路径,原本img自带的src放一张默认图片
            const img = entry.target
            const data_src = img.getAttribute('data-src')
            img.setAttribute('src', data_src)
            // 解除观察,有几张图片就触发几次
            observer.unobserve(img)
        }
    })
}, { threshold: 0.01 }) // 设置触发加载时的视图交叉比例

images.forEach(image => {
    // 对每一个图片对象进行观察
    observer.observe(image)
})

三、Vue2 自定义指令实现

在 main.js 中设置全局自定义指令,命名为 lazy,实际使用时则为 v-lazy

// 定义懒加载图片或者文件等,自定义指令
Vue.directive('lazy', (el, binding) => {
  let oldSrc = el.src //保存旧的src,方便后期渲染时候赋值src真实路径
  el.src = "" //将渲染的src赋为空,则不会渲染图片出来
  let observer = new IntersectionObserver(([{ isIntersecting }]) => { // 调用方法得到该elDOM元素是否处于可视区域
    if (isIntersecting) { //回调是否处于可视区域,true or false
      el.src = oldSrc //如果处于可视区域额,将最开始保存的真实路径赋予DOM元素渲染
      observer.unobserve(el) // 只需要监听一次即可,第二次滑动到可视区域时候不在监听
    }
  }, { threshold: 0 }) // 设置阈值
  observer.observe(el) // 调用方法
})

四、Vue3 自定义指令实现

vue3 的指令拥有的钩子函数和组件的一样,使用指令的DOM是否创建好,钩子函数: mounted

export default {
  install (app) {
    // 定义指令
    defineDirective(app)
  }
}
// 定义指令
const defineDirective = (app) => {
  // 图片懒加载
  app.directive('lazy', {
    // vue2 监听使用指令的DOM是否创建好 钩子函数: inserted
    // vue3 的指令拥有的钩子函数和组件的一样,使用指令的DOM是否创建好,钩子函数: mounted
    mounted (el, binding) {
      // 创建一个观察对象,来观察当前使用指令的元素
      const observer = new IntersectionObserver(([{ isIntersecting }]) => {
        if (isIntersecting) {
          console.log('您已进入一级战备状态')
          // 停止观察
          observer.unobserve(el)
          // 加载失败时,设置默认展示图片
          el.onerror = () => {
            el.src = defaultImg
          }
          // 把指令的值设置给el的src属性 bingding.value就是指令的值
          el.src = binding.value
        }
      }, { threshold: 0 })
      observer.observe(el)
    }
  })
}

兼容性

目前基本已经支持所有浏览器,无需担忧。
MDN上的关于 Intersection Observer API 兼容性的信息

总结

本文后续还将增加scroll和Vue3的useIntersectionObserver插件等方法。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue3 中,可以使用 `Intersection Observer` 实现图片的懒加载。下面是一个使用 TypeScript 实现图片懒加载示例: 安装 `intersection-observer` 库: ```bash npm install intersection-observer --save ``` 创建一个 `LazyImage` 组件: ```vue <template> <img :src="placeholder" :data-src="src" /> </template> <script lang="ts"> import { defineComponent, ref, onMounted } from 'vue'; import 'intersection-observer'; export default defineComponent({ props: { src: { type: String, required: true, }, placeholder: { type: String, default: 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=', }, }, setup(props) { const imageRef = ref<HTMLImageElement | null>(null); const observer = new IntersectionObserver((entries) => { entries.forEach((entry) => { if (entry.isIntersecting) { const img = entry.target as HTMLImageElement; img.src = img.dataset.src || ''; observer.unobserve(img); } }); }); onMounted(() => { if (imageRef.value) { observer.observe(imageRef.value); } }); return { imageRef, }; }, }); </script> ``` 在父组件中使用 `LazyImage` 组件: ```vue <template> <div> <lazy-image src="https://example.com/image1.jpg" /> <lazy-image src="https://example.com/image2.jpg" /> <lazy-image src="https://example.com/image3.jpg" /> </div> </template> <script lang="ts"> import { defineComponent } from 'vue'; import LazyImage from './LazyImage.vue'; export default defineComponent({ components: { LazyImage, }, }); </script> ``` `LazyImage` 组件中,使用 `Intersection Observer` 监听图片是否进入视野,如果进入视野,则加载图片;如果未进入视野,则不加载图片,以此实现图片懒加载的效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值