Intersection Observer Api 实现了图片懒加载和上划加载更多

40 阅读2分钟
  • **IntersectionObserver被创建,则无法更改其配置,**所以一个给定的观察者对象只能用来监听可见区域的特定变化值;然而,你可以在同一个观察者对象中配置监听多个目标元素。

  • IntersectionObserver是浏览器原生提供的构造函数,接受两个参数:callback是可见性变化时的回调函数,option是配置对象(该参数可选)。构造函数的返回值是一个观察器实例。实例的observe方法可以指定观察哪个 DOM 节点。

方法:


IntersectionObserver.observe()     使`IntersectionObserver`开始监听一个目标元素。

IntersectionObserver.unobserve()   使IntersectionObserver停止监听特定目标元素。

IntersectionObserver.disconnect()  使IntersectionObserver对象停止监听工作。

IntersectionObserver.takeRecords()  返回所有观察目标的IntersectionObserverEntry对象数组。

使用:这里我用了Vue 的 directives 和 IntersectionObserver 做的图片懒加载,跟着敲一遍就会了。


<div class="list" v-for="(item, index) in tapList" :key="index">

      <!-- src 替换为 v-lazy -->

      <img v-lazy="item.author.avatar_url" alt />

</div>

// 图片的懒加载

directives: {

      // bing 是一个对象 里面有 自定义指定传过来的值 也就是 v-lazy="item.author.avatar_url" 等号里的数据

      // el 可以拿到当前的元素

      lazy(el, bing) {

       // new IntersectionObserver 创建我们的交叉观察器

      let ob = new IntersectionObserver(

        (changes) => {

          // changes 是个数组包含所有的监听对象和视口的交叉位置

          changes.forEach((item) => {

            if (item.isIntersecting) { //  item.isIntersecting == 1 为 true

              //  当先监听的对象 符合条件

              let lazyImg = item.target; // 拿到当前监听的盒子

              // 改变src

              el.src = bing.value;

              // 加载完移除监听

              ob.unobserve(lazyImg);

            }

          });

        },

        {

          // threshold 控制交叉状态在什么养的情况下触发上面的回调

          threshold: [1], // 0 一露头 0.5 露一半 1 完全出现

        }

      );

      // 使`IntersectionObserver`开始监听一个目标元素。

      ob.observe(el);

    },

  },

使用: 做了上划加载更多

  • 无限滚动时,最好在页面底部有一个页尾栏(又称sentinels)。一旦页尾栏可见,就表示用户到达了页面底部,从而加载新的条目放在页尾栏前面。这样做的好处是,不需要再一次调用observe()方法,现有的IntersectionObserver可以保持使用。

 <!-- 加载中的结构 -->

    <div v-show="tapList.length" ref="loading" class="loading">加载中...</div>

 <!-- 仅供参考 -->

    mounted() {

    let loading = this.$refs.loading;

    let ob = new IntersectionObserver(

      (changes) => {

        // changes 包含所有的监听对象和视口的交叉位置

        changes.forEach((item) => {

          // this.tapList.length > 0 防止二次渲染

          if (item.isIntersecting && this.tapList.length > 0) {

            //  当先监听的对象 符合条件

            let lazyImg = item.target; // 当前监听的盒子

            this.params.page++;

            if (this.tapList.length >= this.total) {

              console.log("到底了");

              loading.innerHTML = "到底了兄弟";

              return;

            }

            this.getTapListFn();

            console.log(this.total);

          }

        });

      },

      {