Vue3 实现图片懒加载

97 阅读1分钟

实现图片懒加载

  1. 自定义指令
<template>
  <div class="box">
    <div>
      <img v-lazy="item" alt="" v-for="(item, index) in arr" :key="index" style="width:400px; height:300px">
    </div>
  </div>
</template>
 
<script setup lang='ts'>
import { Directive } from 'vue';
let vLazy: Directive<HTMLImageElement, string> = async (el, binding) => {
  let defaultImage = await import('./assets/defaultImage/vue.svg') // 默认图片
  el.src = defaultImage.default
  observer.observe(el)
}
  1. 引入图片
    import.meta.glob官方文档,globEager已经废弃。
<script setup lang='ts'>
import { Directive } from 'vue';
/*
  glob相当于,是异步的
  let modules  = {
    "xxxx" :()=>import ('xx')
  }
  */
// globEager相当于import 'xxx' from 'xxx'
// let imageList: Record<string, { default: string }> = import.meta.glob('./assets/image/*.*', { eager: true })
let imageList: Record<string, { default: string }> = import.meta.globEager('./assets/image/*.*')
let arr = Object.values(imageList).map(v => { return v.default })
</script>
  1. js 的 IntersectionObserver API
    官方文档,这里主要用到的是IntersectionObserverEntry.intersectionRatio ,用于检测当前在根的交叉比中有多少目标元素可见,值介于0.0和1.0之间。

image.png

image.png

<script setup lang='ts'>
import { Directive } from 'vue';
// let imageList: Record<string, { default: string }> = import.meta.glob('./assets/image/*.*', { eager: true })
let imageList: Record<string, { default: string }> = import.meta.globEager('./assets/image/*.*')
let arr = Object.values(imageList).map(v => { return v.default })
let vLazy: Directive<HTMLImageElement, string> = async (el, binding) => {
  let defaultImage = await import('./assets/defaultImage/vue.svg')
  el.src = defaultImage.default
  const observer = new IntersectionObserver((entry) => {
    if (entry[0].intersectionRatio > 0) {
      setTimeout(() => {
        el.src = binding.value    // 替换默认图片
        observer.unobserve(el)
      }, 1000)
    }
  })
  observer.observe(el)
}
</script>