分页加载数据---Intersection Observer接口

滚动到指定位置加载数据—Intersection Observer接口

(Web API ) IntersectionObserver 接口 (从属于Intersection Observer API) 提供了一种异步观察目标元素与其祖先元素或顶级文档视窗 (viewport) 交叉状态的方法。祖先元素与视窗 (viewport) 被称为根 (root)。

当一个IntersectionObserver对象被创建时,其被配置为监听根中一段给定比例的可见区域。一旦 IntersectionObserver 被创建,则无法更改其配置,所以一个给定的观察者对象只能用来监听可见区域的特定变化值;然而,你可以在同一个观察者对象中配置监听多个目标元素。

IntersectionObserverEntry

IntersectionObserverEntry 的实例作为 entries 参数被传递到一个IntersectionObserver 的回调函数中

属性
  • IntersectionObserverEntry.boundingClientRect :
    返回包含目标元素的边界信息的DOMRectReadOnly. 边界的计算方式与 Element.getBoundingClientRect() 相同。
  • IntersectionObserverEntry.intersectionRatio :
    返回intersectionRect 与 boundingClientRect 的比例值。
  • IntersectionObserverEntry.intersectionRect :
    返回一个 DOMRectReadOnly 用来描述根和目标元素的相交区域。
  • IntersectionObserverEntry.isIntersecting :
    返回一个布尔值,如果目标元素与交叉区域观察者对象 (intersection observer) 的根相交,则返回 true .如果返回 true, 则 IntersectionObserverEntry 描述了变换到交叉时的状态; 如果返回 false, 那么可以由此判断,变换是从交叉状态到非交叉状态。
  • IntersectionObserverEntry.rootBounds :
    返回一个 DOMRectReadOnly 用来描述交叉区域观察者 (intersection observer) 中的根。
  • IntersectionObserverEntry.target :
    与根出现相交区域改变的元素 (Element).
  • IntersectionObserverEntry.time :
    返回一个记录从 IntersectionObserver 的时间原点 (time origin) 到交叉被触发的时间的时间戳 (DOMHighResTimeStamp).

entries 图解

在这里插入图片描述

  • time:发生相交到相应的时间,毫秒。
  • rootBounds:根元素矩形区域的信息,如果没有设置根元素则返回 null,图中蓝色部分区域。
  • boundingClientRect:目标元素的矩形区域的信息,图中黑色边框的区域。
  • intersectionRect:目标元素与视口(或根元素)的交叉区域的信息,图中蓝色方块和粉红色方块相交的区域。
  • isIntersecting:目标元素与根元素是否相交,true为相交
  • intersectionRatio:目标元素与视口(或根元素)的相交比例。
  • target:目标元素,图中黑色边框的部分。

使用

当滚动到loading目标元素后显示

import React, { useState, useEffect } from 'react';
import { history } from 'umi';

let Observer;
export default function (props) {
    const [state, setState] = useState()

    useEffect(() => {
        
        let dom = document.querySelector('#loading')

        console.log('进入页面');
        if (dom) {
            Observer = new IntersectionObserver(function (entries) {
                console.log(entries);
                ...
            })
        }

        //Observer开始监听一个目标元素
        Observer.observe(dom)

        return () => {
            console.log('离开页面');

            if (Observer) {
                if (dom) {
                    // 停止监听特定目标元素
                    Observer.unobserve(dom);

                    // Observer对象停止监听工作
                    Observer.disconnect()
                }
            }
        }
    }, [])

    const handleClick = () => {
        history.push('/')
    }

    return (
        <div>
            ...
            
            <div id='loading' style={{ width: '100px', height: '100px', background: 'red', marginTop: '1000px' }}>loading</div>
        </div>
    )
}

自定义hook—useObserverHook.js

import { useEffect } from 'react';

let observer;
export default function useObserverHook(ele, callback, watch = []) {
    useEffect(() => {
    	//node目标元素
        const node = document.querySelector(ele);
        if (node) {
            observer = new IntersectionObserver(entries => {
                callback && callback(entries)
            })
             //开始监听目标元素
             observer.observe(node)
        }

        return () => {
            if (observer && node) {
                // 停止监听特定目标元素
                observer.unobserve(node);

                // Observer对象停止监听工作
                observer.disconnect()
            }
        }
    }, watch)
}

使用自定义hook

//使用hook
...
import { useObserverHook } from '@/hook/index.js'
...
useObserverHook('#loading', (entries) => {
        console.log(entries);
        //滚动到底部加载下一页
        //entries[0].isIntersecting为true即进入目标元素
        if (entries[0].isIntersecting) {
            setPage({
                ...page,
                pageNum: page.pageNum + 1
            })
        }
    },null)

useEffect第二个参数

useEffect(()=>{},[])第二个参数

  • 不传参,每次state变动都会触发;
  • 参数为空数组,只执行一次,state变动不会触发;
  • 参数为数组,并且有依赖项,那么每当依赖项有变动时候会触发;
  • null,不监听任何依赖项

更多文章可访问博客

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值