vue3 组合式api 实现v-lazy 图片懒加载

前置知识

Intersection Observer

浏览器提供api,用于检测目标元素和祖先元素/顶级文档视窗 (viewport) 交叉状态的方法。

    const observer = new IntersectionObserver(function (IntersectionObserverEntry) {},options);
    observer.observe(el);

构造函数接收一个回调函数,一个配置对象(可选),返回一个观察器实例。实例的observe方法接收一个dom节点作为观察的对象
当目标对象出现在视口的时候,会调用回调函数,传递一个元素都为IntersectionObserverEntry对象的数组。
IntersectionObserverEntry对象有以下属性 (只列举了这篇用到的两个):

  • target:被观察的目标元素,是一个 DOM 节点对象
  • intersectionRatio:目标元素的可见比例,即intersectionRect占boundingClientRect的比例,完全可见时为1,完全不可见时小于等于0

Vue3指令周期

  • created:在绑定元素的 attribute 或事件监听器被应用之前调用;

  • beforeMount:当指令第一次绑定到元素并且在挂载父组件之前调用;

  • mounted:在绑定元素的父组件被挂载后调用;

  • beforeUpdate:在更新包含组件的 VNode 之前调用;

  • updated:在包含组件的 VNode 及其子组件的 VNode 更新后调用;

  • beforeUnmount:在卸载绑定元素的父组件之前调用;

  • unmounted:当指令与元素解除绑定且父组件已卸载时,只调用一次;

image对象

Image 对象代表嵌入的图像。

  • onload 当图像装载完毕时调用的回调函数。

思路

  • 想要的效果 在有多个图片加载的时候 只要在最外面的wrapper上用一次v-lazy就可以
  • 每张图片的src先用加载gif替换掉,然后再放到文档碎片里面,等到用户滑动到视口了再挂载上图片元素,之前一直使用加载的gif占位,等图片加载完成再替换。
     首先vue3的指令跟组件类似也有生命周期,created的时候指令绑定的dom元素还没有attribute,也没有DOM结构,所以不适合,mounted整个DOM元素已经挂载到页面上了,图片在挂载上去的时候就开始加载,再做懒加载已经没有意义了,所以使用beforeMount,有完整的DOM结构,但是没有挂载到页面上。

完整代码

export const lazyLoad = {
  beforeMount(el: any, binding: any, vnode: any, prevVnode: any) {
    const img = el.querySelector(`.${el.className} img`);
    const src = img.getAttribute("src");
    // 图片使用loading gif替换
    img.setAttribute("src", "https://m.tea7.com/images/imgLoading.gif");
    // 新建Image对象
    const tempImg = new Image();
    tempImg.onload = function () {
      img.setAttribute("src", src);
    };
    const parent = img.parentNode;
    const observer = new IntersectionObserver(function (changes) {
      // 可视
      changes.forEach((item) => {
        if (item.intersectionRatio !== 0) {
          tempImg.src = src;
        }
      });
    });
    observer.observe(el);
  },
};

参考链接:
IntersectionObserver API 使用教程

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值