性能优化之滚动监听及示例

935 阅读2分钟

前言

  • 需求背景:需要监听某个元素的滚动位置触发对应事件(懒加载无限滚动等),比如:
    • 向下滚动时,显示/隐藏某个元素;
    • 元素滚动进入某个区域/位置等
  • 采取方案
    • 传统方式:添加scroll 事件监听,时刻获取目标元素的滚动情况
      • 缺点:滚动事件会频繁触发,计算工作大,加重性能方面的负担
    • IntersectionObserver API:通过异步监听观察元素是否进入可见区域**,不需要时刻触发

IntersectionObserver API

  • 定义:一种异步观察目标元素与规定的视窗的交叉状态的方法(不随目标元素滚动同步触发

    • 目标元素:需要监听的DOM节点元素
    • 视窗:默认是网页可见区域,也可自行设置,但必须是目标元素的祖先元素
  • 创建对象实例:var io = new IntersectionObserver(callback, options)

  • 配置触发参数:options:(可选),属性如下:

    • root/rootMargin:目标元素的祖先节点及其margin
    • threshold:数组阈值,达到或超过设定的值时触发回调 (可决定何时触发回调)
  • 触发回调callback(entries): 当目标元素与视口交叉(进入视口区域)时

    • 注意点:一般会触发两次,第一次是元素刚进入可视区,第二次是完全离开可视区
    • entries:数组,每一项表示一个观察元素与视窗的交叉状态对象(IntersectionObserverEntry)
  • IntersectionObserverEntry常用属性:

    • time:可见性发生变化的时间
    • target:被观察的目标 DOM 节点对象
    • rootBounds:根元素的矩形区域的信息
      • getBoundingClientRect()方法的返回值,没有根元素则返回null
    • boundingClientRect:目标元素的矩形区域
    • intersectionRect:交叉区域的信息
    • isIntersecting:true(有交叉区域);false(无交叉区域)
    • intersectionRatio:目标元素在交叉区域可见比例,即intersectionRectboundingClientRect的比例,完全可见时为1,完全不可见时小于等于0
  • 方法:

    • 开始观察目标节点:io.observe(target)
      • target:观察目标DOM节点,监听多个节点需要多次调用
    • 停止观察:io.unobserve(target)
    • 关闭观察:io.disconnect(target)
  • 示例:页面视频滚动至不可见时暂停播放

    • 观察目标元素:底部logo或者距离底部最近的可见元素
var io = new IntersectionObserver(handleObserve,{
    threshold:[0]
})
var targetDom = document.getElementById('video')
//观察
io.observe(targetDom)

//监听回调
function handleObserve(entries){
    if(entries[0].intersectionRatio === 0){
        //视频不可见时,暂停视频
    }
}

//不需要时停止观察
beforeDestroy(){
    io.unobserve(targetDom)
    io.disconnect()
}

image.png