js图片懒加载,在不做分页的情况下的解决方案

发布时间 2024-01-12 00:47:20作者: jialiangzai
Intersection Observer API
1.注意点 一般都是后端返回数据,
用 
this.$nextTick(() => {
          this.handleScroll();
});
确保dom加载完成触发我们定制的handleScroll


handleScroll() {
      const containerRect = this.$refs.container.getBoundingClientRect();
      const observer = new IntersectionObserver((entries) => {
        entries.forEach((entry) => {
          if (entry.isIntersecting) {
            const img = entry.target;
            img.src = img.dataset.src;
            observer.unobserve(img);
          }
        });
      });

      const imgs = this.$refs.container.querySelectorAll('img');
      imgs.forEach((img) => {
        observer.observe(img);
      });
    },
	
<template>
  <view ref="container" @scroll="handleScroll">
    <image v-for="image in images" :key="image.id" :src="image.src" data-src="加载时的占位图" lazy />
  </view>
</template>

<style>
.container {
  height: 100vh;
  overflow-y: scroll;
}
</style>
Scroll Event
this.$nextTick(() => {
          this.handleScroll();
});

 handleScroll() {
      const containerRect = this.$refs.container.getBoundingClientRect();
      const imgs = this.$refs.container.querySelectorAll('img');

      imgs.forEach((img) => {
        const imgRect = img.getBoundingClientRect();
        if (imgRect.top >= containerRect.top && imgRect.bottom <= containerRect.bottom) {
          img.src = img.dataset.src;
        }
      });
    },

<template>
  <view ref="container" @scroll="handleScroll">
    <image v-for="image in images" :key="image.id" :src="image.src" data-src="加载时的占位图" lazy />
  </view>
</template>

<style>
.container {
  height: 100vh;
  overflow-y: scroll;
}
</style>

uni.createSelectorQuery
 this.$nextTick(() => {
          this.handleScroll();
});
handleScroll() {
      const containerRect = uni.createSelectorQuery().select('.container').boundingClientRect();
      const imgs = uni.createSelectorQuery().selectAll('.container image');
      containerRect.exec((rect) => {
        imgs.exec((nodes) => {
          nodes.forEach((node, index) => {
            const imgRect = node.boundingClientRect;
            if (imgRect.top >= rect.top && imgRect.bottom <= rect.bottom) {
              this.images[index].src = this.images[index].src; // 触发图片加载
            }
          });
        });
      });
    },
注册全局指令
import lazyImg from './lazyImg';
Vue.directive('lazy-img', lazyImg);


// lazyImg.js

export default {
  mounted(el, binding) {
    const options = {
      root: null,
      rootMargin: '0px',
      threshold: 0.1,
    };

    let hasLoaded = false; // 标记图片是否已加载

    const observer = new IntersectionObserver((entries) => {
      entries.forEach((entry) => {
        if (entry.isIntersecting && !hasLoaded) { // 添加判断,当图片未加载时触发
          const img = new Image();
          img.src = binding.value;

          img.onload = () => {
            el.setAttribute('src', binding.value);
            observer.unobserve(el);
            hasLoaded = true; // 标记图片已加载
          };
        }
      });
    }, options);

    observer.observe(el);
  },
};