IntersectionObserver

29 阅读2分钟

Intersection Observer API

是⼀种⽤于异步检查⽂档中元素与视⼝叠加程度的API。

1、可以将其⽤于检测图⽚是否已经进⼊视⼝,并根据需要进⾏相应的处理。 图片懒加载

2、 可以用于视口的 曝光加载

mdn 连接

IntersectionObserverEntry 对象的属性

  • boundingClientRect: 目标元素的边界矩形。
  • intersectionRatio: 目标元素与根元素(或视口)相交的比例,介于 0.0 和 1.0 之间。
  • intersectionRect: 目标元素与根元素(或视口)相交区域的矩形。
  • isIntersecting: 一个布尔值,指示目标元素是否与根元素(或视口)相交。
  • rootBounds: 根元素的边界矩形,如果根元素是视口则为视口的边界矩形。
  • target: 被观察的目标元素。
  • time: 这个交集改变发生的时间戳。
// 曝光加载
​
​
<template>
  <div class="scroll-box" ref="scollbox" :style="'max-height:' + height">
    <slot></slot>
    <div ref="endBox" class="add-more">
      {{ !end ? (isloading ? "加载中..." : "加载完成") : "没有更多了" }}
    </div>
  </div>
</template><script>
/**
 * isloading 默认为 false,在元素曝光后执行加载 ,为 true时候为加载中,
 * 每次加载过程中都会改变 isloading 为 true,加载完成后 外面设置 isloading = false
 * end 默认为 false 可以加载更多, 为 true 时候注销监听
 * @send 发起加载请求
 */
export default {
  props: {
    isloading: {
      type: Boolean,
      default: false,
    },
    height: {
      type: String,
      default: "270px",
    },
    end: {
      type: Boolean,
      default: false,
    },
  },
  data() {
    return {
      observer: "",
    };
  },
  watch: {
    end(val) {
      if (val) {
        if (this.observer) {
          this.observer.disconnect();
        }
      }
    },
  },
  mounted() {
    this.initScrollHandle();
  },
  methods: {
    initScrollHandle() {
      this.observer = new IntersectionObserver(
        (changes) => {
          const change = changes[0];
          if (change.intersectionRatio > 0.1) {
            // 曝光加载
            this.starLoad();
          }
        },
        {
          root: this.$refs.scollbox,
          threshold: 0.2,
        }
      );
      // this.$refs.scollbox
      if (!this.end) {
        this.addObserve();
      }
    },
    addObserve() {
      const { observer } = this;
      if (observer) {
        observer.observe(this.$refs.endBox);
      }
    },
    starLoad() {
      if (!this.isloading) {
        console.log("执行send");
        this.$emit("send");
        this.$emit("update:isloading", true); // 加载过程中为 false // 加载完成改为 ture 可以继续加载
      }
    },
  },
};
</script><style lang="scss" scoped>
.scroll-box {
  height: 270px;
  overflow: hidden;
  overflow-y: auto;
  margin-bottom: 8px;
  &::-webkit-scrollbar {
    width: 15px;
    height: 15px;
  }
​
  &::-webkit-scrollbar-thumb {
    background-color: var(--color-on-light-600);
    background-clip: content-box;
    border: 4px solid transparent;
    border-radius: 8px;
  }
  &::-webkit-scrollbar-thumb:hover {
    background-color: var(--color-on-light-700);
  }
  &::-webkit-scrollbar-track {
    background-color: #fff;
    box-shadow: inset;
  }
}
.add-more {
  text-align: center;
  font-size: 12px;
  color: #333;
}
</style>

图片懒加载

function lazyLoadImages(imgSelector) {
  const images = document.querySelectorAll(imgSelector);
  const config = {
    rootMargin: '0px 0px 50px 0px',
    threshold: 0
  };
 
  const observer = new IntersectionObserver(function(entries, self) {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        const img = entry.target;
        const src = img.getAttribute('data-src');
        img.src = src;
        self.unobserve(img);
      }
    });
  }, config);
 
  images.forEach(img => {
    observer.observe(img);
  });
}
 
// 使用时,确保在文档加载完成后调用
document.addEventListener('DOMContentLoaded', function() {
  lazyLoadImages('img[data-src]');
});