懒加载处理,不要再傻傻监听页面滚动

Posted 前端修罗场

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了懒加载处理,不要再傻傻监听页面滚动相关的知识,希望对你有一定的参考价值。

本文转载自作者:孤月葬花魂
链接:https://juejin.cn/post/7099365196841353230
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

懒加载处理

利用浏览器原生提供的构造函数 IntersectionObserver, 不要再傻傻监听页面滚动

一、IntersectionObserver简介

1. 语法

let observer = new IntersectionObserver(callback, option);

/*
  callback 是当被监听元素的可见性变化时,触发的回调函数
  option 是一个配置参数,可选,有默认的属性值
*/

2. callback 参数

目标元素的可见性变化时,就会调用观察器的回调函数 callback

callback 一般会触发两次。一次是目标元素刚刚进入视口(开始可见),另一次是完全离开视口(开始不可见)。

let observer = new IntersectionObserver(
  entries => 
    /*
      entries是一个数组,每个成员都是一个IntersectionObserverEntry对象
      如果同时有两个被观察的对象的可见性发生变化,entries数组就会有两个成员
    */
    console.log(entries);
  );

3. IntersectionObserverEntry 对象

IntersectionObserverEntry 对象提供目标元素的信息,一共有六个属性

  • time: 可见性发生变化的时间,是一个高精度时间戳,单位为毫秒;

  • target: 被观察的目标元素,是一个 DOM 节点对象;

  • rootBounds: 根元素的矩形区域的信息,getBoundingClientRect()方法的返回值,如果没有根元素(即直接相对于视口滚动),则返回 null;

  • boundingClientRect: 目标元素的矩形区域的信息;

  • intersectionRect: 目标元素与视口(或根元素)的交叉区域的信息;

  • intersectionRatio: 目标元素的可见比例,即 intersectionRectboundingClientRect 的比例,完全可见时为1,完全不可见时小于等于0;

4. option 对象

4.1 threshold 属性
new IntersectionObserver(
  entries => 
    // do something
  , 
  
    threshold: [0, 0.25, 0.5, 0.75, 1]
  
);

/*
  threshold属性决定了什么时候触发回调函数。
  它是一个数组,每个成员都是一个门槛值,默认为[0],即交叉比例(intersectionRatio)达到0时触发回调函数。

  用户可以自定义这个数组。
  比如,[0, 0.25, 0.5, 0.75, 1]就表示当目标元素 0%、25%、50%、75%、100% 可见时,会触发回调函数。
*/
4.2 root 属性,rootMargin 属性
new IntersectionObserver(
  entries => 
    // do something
  , 
  
    root: document.querySelector('#box'),
    rootMargin: '10px 20px 30px 40px'
  
);

/*
  root属性指定目标元素所在的容器节点(即根元素)。注意,容器元素必须是目标元素的祖先节点。

  rootMargin定义根元素的margin,
  用来扩展或缩小rootBounds这个矩形的大小,从而影响intersectionRect交叉区域的大小。
  它使用CSS的定义方法,比如10px 20px 30px 40px,表示 top、right、bottom 和 left 四个方向的值。

  这样设置以后,不管是窗口滚动或者容器内滚动,只要目标元素可见性变化,都会触发观察器。
*/
5. 注意

IntersectionObserver API 是异步的,不随着目标元素的滚动同步触发。
规格写明,IntersectionObserver的实现,应该采用requestIdleCallback(),即只有线程空闲下来,才会执行观察器。
这意味着,这个观察器的优先级非常低,只在其他任务执行完,浏览器有了空闲才会执行。

二、应用,以指令形式

<template>
  <div v-lazy-component="init">
  </div> 
</template>

<script>
export default 
  directive: 
    'lazy-component': 
      // 只调用一次
      bind(el, binding) 
        // 判断是否可以使用
        if ('IntersectionObserver' in window) 
          // IntersectionObserver对象,浏览器原生提供的构造函数
          let observer = new IntersectionObserver((entries) => 
            // intersectionRatio: 目标元素的可见比例,即intersectionRect占boundingClientRect的比例,完全可见时为1,完全不可见时小于等于0
            // 是否交叉
            const isIntersected = entries.some(entry => entry.intersectionRatio > 0);
            if (isIntersected) 
              // 执行绑定的事件
              binding.value();

              // 停止观察
              observer.unobserve(el);

              // 关闭观察器
              observer.disconnect();
            
          );

          // 开始观察, el: DOM对象
          observer.observe(el);
         else 
          binding.value();
        
      
    
  ,

  methods: 
    init() 
      // do something
    
  

</script>

以上是关于懒加载处理,不要再傻傻监听页面滚动的主要内容,如果未能解决你的问题,请参考以下文章

节流函数与页面滚动处理的一些方式

懒加载

VUE 实现监听滚动事件,实现数据懒加载

图片懒加载和预加载

前端技术--懒加载

今天遇到的问题,解决UITableView页面上面的内容先被导航栏覆盖,然后再向下移动的问题 ( 懒加载有时候并不好! )