您好,如果喜欢我的文章,可以关注我的公众号「量子前端」,将不定期关注推送前端好文~
懒加载组件,支持任意元素进行延迟加载,可以在SPA单页应用首页渲染时减少非可视区的DOM渲染,加快首屏渲染效率,大致用法:
<LazyLoad>
<div>
<span>需要被懒加载的一些元素</span>
.......
</div>
</LazyLoad>
这一期的文档比较简单,主要就是支持懒加载包裹元素,没有很多的API,如下:
组件源码:
import React, {
FC, memo, useEffect, useState, createRef } from 'react';
interface LazyLoadProps {
children?: any;
/**
* @description 延迟加载
* @default 0ms
*/
delay?: number;
}
const LazyLoad: FC<LazyLoadProps> = (props) => {
const {
children, delay } = props;
const [showEl, setShowEl] = useState(false);
const lazyRef = createRef();
let io: IntersectionObserver; //观察者
useEffect(() => {
io = new IntersectionObserver((entries) => elementObverse(entries));
io.observe(lazyRef.current as Element);
}, []);
const elementObverse = (entries: Array<IntersectionObserverEntry>) => {
//监听函数
entries.forEach((entry: IntersectionObserverEntry) => {
if (entry.isIntersecting) {
if (delay) {
setTimeout(() => {
setShowEl(true);
}, delay);
} else {
setShowEl(true);
}
}
});
};
return (
<div className="lazyLoad" ref={
lazyRef as any}>
{
showEl && children}
</div>
);
};
export default memo(LazyLoad);
主要使用了IntersectionObserver这个类来监听懒加载的元素是否在可视区,来决定加载实现的。
然后顺便一起记录一下IntersectionObserver这个API的使用吧。
Intersection Observer 的概念和用法
Intersection Observer API提供了一种异步检测目标元素与祖先元素或 viewport 相交情况变化的方法,可以自动“观察”元素是否可见,可见的本质是目标元素与视口产生一个交叉区域,所以这个 API 叫做“交叉观察器”
Intersection Observer API 允许你配置一个回调函数,每当目标(target)元素与设备视窗或者其他指定元素发生交集的时候执行。设备视窗或者其他元素我们称它为根元素或根(root)。通常,您需要关注文档最接近的可滚动祖先元素的交集更改,如果元素不是可滚动元素的后代,则默认为设备视窗。如果要观察相对于根(root)元素的交集,请指定根(root)元素为null
创建 IntersectionObserver 对象
var intersectionObserver = new IntersectionObserver(callback, option);
当一个 IntersectionObserver 对象被创建时,其被配置为监听根中一段给定比例的可见区域。一旦 IntersectionObserver 被创建,则无法更改其配置,所以一个给定的观察者对象只能用来监听可见区域的特定变化值;然而,你可以在同一个观察者对象中配置监听多个目标元素。
callback 回调函数
当目标元素的可见性变化时,就会调用观察器的 callback 回调函数,回调函数的参数是一个数组,每个成员都是一个 IntersectionObserverEntry 对象
IntersectionObserverEntry 对象属性:
- time:可见性发生变化的时间,是一个高精度时间戳,单位为毫秒
- target:被观察的目标元素,是一个 DOM 节点对象
- rootBounds:根元素的矩形区域的信息,getBoundingClientRect()
方法的返回值,如果没有根元素(即直接相对于视口滚动),则返回 null - boundingClientRect:目标元素的矩形区域的信息
- intersectionRect:目标元素与视口(或根元素)的交叉区域的信息
- intersectionRatio:目标元素的可见比例,即 intersectionRect 占 boundingClientRect
的比例,完全可见时为 1,完全不可见时小于等于0 - isIntersecting:目标元素当前是否可见
配置对象 option
root:指定目标元素所在的容器节点(即根元素),该元素必须是目标元素的祖先节点。如果未传入值或值为 null,则默认使用顶级文档的视窗
rootMargin:定义根元素的 margin,用来扩展或缩小 rootBounds 这个矩形的大小,从而影响
intersectionRect 交叉区域的大小。它使用CSS的定义方法,比如10px 20px 30px 40px,表示
top、right、bottom 和 left 四个方向的值threshold:决定了什么时候触发回调函数。它是一个数组,每个成员都是一个门槛值,默认为[0],即交叉比例(intersectionRatio)达到0时触发回调函数
由于懒加载设计,我的定义是整个视窗,因此我在源代码里没有加入option的配置,因此是null。
感谢阅读~~~~~
- Concis组件库线上链接:http://react-view-ui.com:92
- github:https://github.com/fengxinhhh/Concis
- npm:https://www.npmjs.com/package/concis