vue3封装一个图片懒加载的自定义指令

功能介绍

利用IntersectionObserver API实现,主要功能

  1. 图片懒加载
  2. 传递一个回调函数,该回调函数会在图片出现时触发,并接收显示的元素。

代码展示

<template>
    <div class="test h-[4000px] bg-slate-400 ">
        <div class="wrapper flex flex-col mx-auto bg-neutral-200 h-full w-[500px] ">
            <img v-for="item of arr " v-load="{src:item,root:null,cb:loadDone}"  alt="风景图"/>
        </div>
    </div>
</template>

<script setup lang='ts'>
const loadDone = (el:HTMLElement) => {
    console.log(el,'执行回调')
}
const arr = [
    '../../../src/assets/scenery/scene1.jpg',
    '../../../src/assets/scenery/scene2.jpg',
    '../../../src/assets/scenery/scene3.jpg',
    '../../../src/assets/scenery/scene4.jpg',
    '../../../src/assets/scenery/scene5.jpg',
    '../../../src/assets/scenery/scene6.jpg',
    '../../../src/assets/scenery/scene6.jpg',
    '../../../src/assets/scenery/scene6.jpg',
    '../../../src/assets/scenery/scene6.jpg',
    '../../../src/assets/scenery/scene6.jpg',
    '../../../src/assets/scenery/scene6.jpg',
]
</script>

<style lang='scss' scoped>
 img{ width: 100%; height: 500px; }
</style>

let observe = false
var elementArr = [] as { el: HTMLElement, src: string, cb: Function | null; }[]
const options = {
    threshold: [0],//threshold:属性决定相交比例为多少时,触发回调函数。取值为 0 ~ 1,或者 0 ~ 1的数组。
    rootMargin: "0px",//rootMargin: 类似于 CSS 的 margin 属性。用来缩小或扩大 rootBounds,从而影响相交的触发 
    root: null,//root:设置监视器的根节点,不传则默认为视口。
}
const observers = new IntersectionObserver(isoCallback,options)
function useLoadDirective() {
    return {
        created(el:HTMLElement,binding:any,vnode:any) {
            elementArr.push({ el, src: binding.value.src,cb: binding.value.cb})
           
        },
        mounted(el:HTMLElement,binding:any) {
            if (!observe) {
                if(binding.value.root)options.root = binding.value.root
                startObserve()
                observe = true
            }
        },
        
    }
}
function isoCallback(entries:any) {
    entries.forEach((element:any,index:number) => {
        if (element.isIntersecting) {
            elementArr.forEach(e => {
                if (e.el == element.target) {
                    element.target.setAttribute('src', e.src)
                    e.cb && e.cb(element.target)
                }
            });
            observers.unobserve(element.target)
        }
    });
}
function startObserve() {
    elementArr.forEach(v => [
        observers.observe(v.el)
    ])
}
useLoadDirective.dName = 'load'
export default useLoadDirective

图片效果展示

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大鲤余

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值