Html5 intersectionObserver

intersectionObserver

监听目标元素与其祖先元素或视口交叉状态

实现懒加载

  observeVisible = () => {
    /**
     * @param {function} callback - 目标元素可见性发生变化时调用,一般会触发两次,目标刚进入视口,目标完全离开视口
                  @param {array} entries - IntersectionObserverEntry对象数组, e.g. 同时有两个被观察对象的可见性发生变化,entries数组就会有两个成员
                          e.g. [{
                                 time: 3893.92,                  // 可见性发生变化的时间戳
                                 intersectionRatio: 0.54,        // 目标元素可见比例,完全可见:1,完全不可见:0
                                 target: element,                // 被观察元素,DOM节点
                                 isIntersecting: true,           // 是否处于相交状态
                                 rootBounds: ClientRect {        // 根元素矩形区域信息,getBoundingClientRect()的返回值,没有根元素返回null
                                    bottom: 920,
                                    height: 1024,
                                    left: 0,
                                    right: 1024,
                                    top: 0,
                                    width: 920
                                 },
                                boundingClientRect: ClientRect { // 目标元素的矩形区域信息
                                   // ...
                                },
                                intersectionRect: ClientRect { // 目标元素与视口(或根元素)的交叉区域信息
                                  // ...
                                }
                              }]
     * @param {object}   option   - 配置,可选
               {
                  threshold: {number || Array},判断元素可见的阀值,[0, 1)
                                                默认为0 || [0],即交叉比例(intersectionRatio),只要交叉比例大于0,e.g. 0.0000001:元素视为可见,0:元素视为不可见
                                                0.8, intersectionRatio > 0.8:元素视为可见,intersectionRatio < 0.8:元素视为不可见
                                                [.5, .8],intersectionRatio > 0.5 || intersectionRatio > 0.8:元素视为可见,触发两次可见的回调,intersectionRatio < 0.5:元素视为不可见,触发一次隐藏的回调
                  root:                         指定视口元素
                  rootMargin:                  用于扩展或缩小视口的大小,从而影响intersection交叉区域的大小
               }
     *
     * @desc 实例方法
     - observer.observe(document.getElementById('example')); // 开始观察
     		参数是一个DOM节点,观察多个节点需多次调用 e.g. observer.observe(elementA); observer.observe(elementB);
     - observer.unobserve(element);                          // 停止观察
     - observer.disconnect();                                // 关闭观察器
     * */
    const observer = new IntersectionObserver((entries) => {
      entries.forEach((item) => {
        // 元素可见
        if (item.intersectionRatio > 0) {
          const element = item.target;

          element.innerText = 'Done';
          observer.unobserve(element);
        }
      })
    });

    const lazyloadItems = document.querySelectorAll('.lazy-loaded');

    Array.from(lazyloadItems).forEach((item) => {
      observer.observe(item);
    })
  };

<div style={{ width: 300, height: 300, overflow: 'auto' }}>
  <div id='1' className='lazy-loaded' style={{ width: 300, height: 150, boxSizing: 'border-box', backgroundColor: 'gray' }}></div>
  <div id='2' className='lazy-loaded' style={{ width: 300, height: 150, boxSizing: 'border-box', backgroundColor: 'gray' }}></div>
  <div id='3' className='lazy-loaded' style={{ width: 300, height: 150, boxSizing: 'border-box', backgroundColor: 'gray' }}></div>
  <div id='4' className='lazy-loaded' style={{ width: 300, height: 150, boxSizing: 'border-box', backgroundColor: 'gray' }}></div>
  <div id='5' className='lazy-loaded' style={{ width: 300, height: 150, boxSizing: 'border-box', backgroundColor: 'gray' }}></div>
</div>

实现无限下拉加载更多

  observeVisible = () => {
    const endItem = document.querySelector('#sentinels');
    const scrollView = document.querySelector('#scrollView');

    const observer = new IntersectionObserver((entries) => {
      entries.forEach((item) => {

        // 底部元素可见
        if (item.intersectionRatio > 0) {

          const newItem = document.createElement('div');
          newItem.style.cssText = 'width:300px; height:150px; background-color:gray';

          scrollView.insertBefore(newItem, endItem);
        }
      })
    });

    observer.observe(endItem);
  };

 <div id='scrollView' style={{ width: 300, height: 300, overflow: 'auto' }}>
   <div style={{ width: 300, height: 150, backgroundColor: 'gray' }}></div>
   <div style={{ width: 300, height: 150, backgroundColor: 'gray' }}></div>
   <div style={{ width: 300, height: 150, backgroundColor: 'gray' }}></div>
   <div style={{ width: 300, height: 150, backgroundColor: 'gray' }}></div>
   <div style={{ width: 300, height: 150, backgroundColor: 'gray' }}></div>
   <div id='sentinels'></div>
 </div>

参考文章:https://www.ruanyifeng.com/blog/2016/11/intersectionobserver_api.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值