vue3 - 使用IntersectionObserver实现懒加载

1. 基础用法

 

<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'
// loading-image
const imgUrl = ref(new URL('/src/assets/loading.png', import.meta.url).href)
let observer: IntersectionObserver
onMounted(() => {
  // 注册观察者
  observer = new IntersectionObserver(entries => {
    for (let index = 0; index < entries.length; index++) {
      // 获取到目标元素img标签
      const target = entries[index].target as HTMLImageElement
      // 观察者返回的对象
      const element = entries[index]
      if (element.isIntersecting) {
        target.src = target.dataset.src ?? ''
        observer && observer.unobserve(target)
      }
    }
  })

  // 遍历所有class为lazy-image的图片
  const imgs: HTMLCollection = document.getElementsByClassName('lazy-image')
  for (const img of Array.from(imgs)) {
    img && observer.observe(img)
  }
  // 断开所有观察
  onUnmounted(() => {
    observer.disconnect()
  })
})
</script>

<template>
  <div class="card" v-for="item in 10" :key="item">
    <img
      class="lazy-image"
      data-src="https://qtfei.com/images/logo.jpg"
      :src="imgUrl"
      alt="某网站logo"
    />
  </div>
</template>

<style scoped>
.read-the-docs {
  color: #888;
}
.card {
  padding: 200px;
}
</style>

 

  

 

2. 自定义一个简单的懒加载指令

main.ts

import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import lazyload from './directives/lazyload'
createApp(App)
  .directive('lazyload', lazyload)
  .mount('#app')

 Vue template

<img v-lazyload="'https://qtfei.com/images/logo.jpg'" :src="imgUrl" alt="某网站logo" />

 

 

lazyload.ts

let observer: IntersectionObserver
function _observer (el: HTMLImageElement, src: string) {
  observer = new IntersectionObserver(entries => {
    for (let index = 0; index < entries.length; index++) {
      // 获取到目标元素img标签
      const target = entries[index].target as HTMLImageElement
      // 观察者返回的对象
      const element = entries[index]
      if (element.isIntersecting) {
        console.log('显示了')
        target.src = src || ''
        observer && observer.unobserve(target)
      }
    }
  })
  observer.observe(el)
}

export default {
  mounted (el: HTMLImageElement, binding: any, vnode: any) {
    _observer(el, binding.value)
  },
  unmounted (el: HTMLImageElement) {
    observer.disconnect()
  }
}
posted @ 2022-09-29 19:34  祁腾飞  阅读(736)  评论(0编辑  收藏  举报