图片懒加载

图片懒加载的原理

1.给图片设置个data- 的自定义属性
2.初始,图片为自定义属性无值
3.当图片可见值data- 属性变为src有值,去加载图片

如何判断元素是否可见?

之前: scrollTop,offsetT,height...计算...

现在: 浏览器有一个API,intersectionObserver 可以监听元素是否可见

开发中,有vueuse中的useIntersectionObserver 这个api

useIntersectionObserver 的基本使用

在 src - views -  .vue

<script setup lang="ts">
import { useIntersectionObserver } from '@vueuse/core'
import { onMounted, ref } from 'vue';

const imgRef = ref(null)
// 实时这个dom是否在可视区内
// const { stop } = useIntersectionObserver(要监视的dom, ([{ isIntersecting }]) => {
//    // 回调函数: 当 isIntersecting 变化时:从可见->不可见; 不可见->可见
//    isIntersecting: 当前是否可见?
// })

// stop: 停止监听

onMounted(() => {
  const { stop } = useIntersectionObserver(imgRef.value, ([ { isIntersecting }]) => {
    console.log('是否进入?', isIntersecting )
  } )

  setTimeout(() => {
    console.log('停止监视...')
    stop()
  }, 5000)
})
</script>
<template>
   <img ref="imgRef" width="200" height="200" /> 
</template>

封装自定义指令

src/directive/directive.ts

import { useIntersectionObserver } from "@vueuse/core";
import { App } from "vue";

//自定义指令
export default {
  install(app:App) {
    //全局指令
    app.directive('lazy',{
      //mounted是
      mounted (el,binding) {
        console.log('lazy',el,binding.value);
        const {stop} = useIntersectionObserver(el,([{isIntersecting}]) =>{
          if (isIntersecting) {
            el.src = binding.value

            //停止
            stop()
          }
        })
      }
    })
  }
}

 src/main.ts

import XtDirective from '@/directive/directive'

app.use(XtDirective)

懒加载图片基本实现

在 src - views - Layout/Layout.vue

<script setup lang="ts">
import { useIntersectionObserver } from '@vueuse/core'
import { onMounted, ref } from 'vue';

const imgRef = ref<null | HTMLImageElement>(null)
// 实时这个dom是否在可视区内
// const { stop } = useIntersectionObserver(要监视的dom, ([{ isIntersecting }]) => {
//    // 回调函数: 当 isIntersecting 变化时:从可见->不可见; 不可见->可见
//    isIntersecting: 当前是否可见?
// })

// stop: 停止监听

onMounted(() => {
  const { stop } = useIntersectionObserver(imgRef.value, ([ { isIntersecting }]) => {
    //console.log('是否进入?', isIntersecting )
    console.log('是否进入?', isIntersecting, imgRef.value?.dataset.src )
  } )
    // 如果图片可见,则设置它的src为 data-src的值
    if(isIntersecting){
      if(imgRef.value){
        imgRef.value.src = imgRef.value.dataset.src || ''
      }
      // 停止观察监听
      stop()
    }
  } )
  
})
</script>
<template>
    <img
      ref="imgRef"
      data-src="https://yanxuan-item.nosdn.127.net/79f289a4e975fd030d5c37b98b9282c5.jpg"
      width="200" height="200" />
</template>

而后在其他文件中 将 :src  改为  v-lazy即可

但是呢,也会出现图片加载失败的情况 - 因此要给图片设置默认图片

在 src/directive/directive.ts中修改

import { useIntersectionObserver } from "@vueuse/core";
import { App } from "vue";

import defaultImg from '../assets/images/loading.gif'
//自定义指令
export default {
  install(app:App) {
    //全局指令
    app.directive('lazy',{
      //el是dom元素
      mounted (el,binding) {
        //设置默认图
        el.src = defaultImg
        //console.log('lazy',el,binding.value);

        //实时监听el是否可见,如果可见,给它的src设置 binding.value
        const {stop} = useIntersectionObserver(el,([{isIntersecting}]) =>{
          if (isIntersecting) {
            el.src = binding.value

            //停止
            stop()
          }
        })
      }
    })
  }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值