当前位置:首页 > 科技  > 软件

20行代码,封装一个 React 图片懒加载组件

来源: 责编: 时间:2024-03-20 08:50:18 130观看
导读一、如何判断图片进入视口我们可以使用传统的方式,监听页面的 scroll 事件,然后调用目标函数的 getBoundingClientRect 方法,得到目标元素在网页中的位置信息。但是我并不喜欢监听 scroll 事件。因为他会大量的执行,并且

kMM28资讯网——每日最新资讯28at.com

一、如何判断图片进入视口

我们可以使用传统的方式,监听页面的 scroll 事件,然后调用目标函数的 getBoundingClientRect 方法,得到目标元素在网页中的位置信息。kMM28资讯网——每日最新资讯28at.com

但是我并不喜欢监听 scroll 事件。因为他会大量的执行,并且 getBoundingClientRect 是一个同步方法,都在主线程上运行,当其频繁执行时可能会导致性能出现问题。kMM28资讯网——每日最新资讯28at.com

我们可以使用另外一种方式来做到同样的效果。他就是 IntersectionObserver。kMM28资讯网——每日最新资讯28at.com

var observer = new IntersectionObserver(callback[, option])

IntersectionObserver 提供了一种异步观察目标元素与其祖先元素或者顶级文档 viewport 交叉状态的方法。其祖先元素或者视口,被称为根 root。当目标元素与根元素在视图上产生交集时,回调函数就会执行。kMM28资讯网——每日最新资讯28at.com

我们也可以在 options 中,自定义配置 root 元素。kMM28资讯网——每日最新资讯28at.com

let options = {  root: document.querySelector("#scrollArea"),  rootMargin: "0px",  threshold: 1.0,};let observer = new IntersectionObserver(callback, options);

options 接受三个参数。kMM28资讯网——每日最新资讯28at.com

root

自定义目标元素的根节点。该节点必须是目标元素的祖先元素。如果未指定,默认为视口。kMM28资讯网——每日最新资讯28at.com

rootMargin

根元素周围的边距。其值可以类似于 CSS 的 margin 属性,例如 10px 20px 30px 40px,以此表示上、右、下、左。这些值夜可以是百分比。在计算交叉点之前,这组值用于增大或者缩小根元素边框的每一侧,默认为 0。kMM28资讯网——每日最新资讯28at.com

threshold

一个数字或者一组数字。表示目标可见度达到多少百分比时,回调函数就应该执行。例如,如果我希望交叉部分每超过目标元素 25% 就执行,那么我就传入 [0, 0.25, 0.5, 0.75, 1]. 默认值为 0。kMM28资讯网——每日最新资讯28at.com

创建的实例有 4 个方法可以让我们使用。kMM28资讯网——每日最新资讯28at.com

  • observer.disconnect() 停止监听。
  • observer.observe(element) 开始监听目标元素。
  • observer.takRecords() 返回所有目标元素的信息对象数组。
  • observer.unobserve(element)停止监听目标元素。

回调函数执行时,接收一个参数,该参数为回调函数提供目标对象的位置信息,一共有六个属性。kMM28资讯网——每日最新资讯28at.com

{  // 回调执行的时间  time: 3893.92,    // 被观察的目标对象  target: element    // 根元素位置信息  rootBounds: ClientRect {    bottom: 920,    height: 1024,    left: 0,    right: 1024,    top: 0,    width: 920  },    // 目标元素位置信息  boundingClientRect: ClientRect {     // ...  },    // 交叉区域矩形的位置大小信息  intersectionRect: ClientRect {    // ...  },    // 元素可见度比例  intersectionRatio: 0.54,}

该参数返回一个数组包含一个或者多个元素的位置信息。kMM28资讯网——每日最新资讯28at.com

二、图片懒加载原理

在浏览器中,展示一张图片,我们使用的是 img 标签。img 标签有一个必须传入的属性 src,当我们不传入 src 时,图片无法加载,一旦传入 src,那么图片就会立即开始加载。kMM28资讯网——每日最新资讯28at.com

因此,我们需要做的事情就是,当图片没有出现在可视区域时,不传入正确的 src 属性,当通过上述的方法判断图片已经出现在可视区域,我们就传入正确的 src,此时图片会立即加载。kMM28资讯网——每日最新资讯28at.com

三、代码实现

首先,我们封装的新组件,一定要继承原有 img 标签的所有能力。先定义一个 Props 类型声明,目前我们并不需要扩展其他的属性,暂时先这样,未来会根据需求的变动逐渐新增新的属性值。kMM28资讯网——每日最新资讯28at.com

interface LazyLoadProps extends DetailedHTMLProps<ImgHTMLAttributes<HTMLImageElement>, HTMLImageElement> {  }

然后我们我要的事情是,除了 src 属性,我们要把其他属性全部直接传给 img 标签,具体方式如下:kMM28资讯网——每日最新资讯28at.com

export default function LazyLoad(props: LazyLoadProps) {  const {src = '', ...other} = props    return (    <img {...other} />  )}

然后我们需要定义一个 ref 属性,用于获取 img 标签的元素对象。kMM28资讯网——每日最新资讯28at.com

export default function LazyLoad(props: LazyLoadProps) {  const {src = '', ...other} = props  const img = useRef(null)  return (    <img ref={img} {...other} />  )}

准备工作做好之后,我们最后只需要借助 useEffect 声明 IntersectionObserver 实例然后监听图片元素即可。kMM28资讯网——每日最新资讯28at.com

export default function LazyLoad(props: LazyLoadProps) {  const {src = '', ...other} = props  const [URL, setURL] = useState('')  const img = useRef(null)  useEffect(() => {    var io = new IntersectionObserver((entries) => {      // @ts-ignore      if (entries[0].intersectionRatio > 0) {        setURL(src)        img.current && io.unobserve(img.current)      }    }, {})       if (img.current) {      io.observe(img.current)    }  }, [])  return (    <img ref={img} src={URL} {...other} />  )}

这样,一个满足基本要求的图片懒加载组件就封装好了。kMM28资讯网——每日最新资讯28at.com

四、扩展思考

在我们做首屏优化的时候,为了能够达到最快的速度渲染页面,图片的加载往往也需要延后,但是又不能延后太多。因此此时的问题是,图片已经出现在可视区域了,我们又应该如何做才能做到懒加载呢?kMM28资讯网——每日最新资讯28at.com

在实践中可能还会遇到的需求变动是,给图片添加一个占位符。然后占位符元素与图片元素的切换不是立即发生的,而是要等到我们确保图片已经全部加载完成之后才发生的,否则的话,可能会出现图片只加载了一小半的视图情况。这又应该如何实现kMM28资讯网——每日最新资讯28at.com

继续优化。我们希望占位符元素与图片元素的切换没那么生硬,而是结合动画渐入渐出,又该如何实现。kMM28资讯网——每日最新资讯28at.com

继续优化,我们希望支持传入 aspectFill 等属性,确保图片的缩放比例,不能因为宽高的设置导致图片比例变形,又该如何实现kMM28资讯网——每日最新资讯28at.com

这些思考就留给大家在实践中去尝试验证了。本文就不在详细介绍。kMM28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-77981-0.html20行代码,封装一个 React 图片懒加载组件

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: Kotlin的扩展(Extension)特性,你了解了吗?

下一篇: 我们一起解锁小程序开发新姿势

标签:
  • 热门焦点
  • 卢伟冰长文解析K60至尊版 对Redmi有着里程碑式的意义

    卢伟冰长文解析K60至尊版 对Redmi有着里程碑式的意义

    在今天的Redmi后性能时代战略发布会结束之后,Redmi总经理卢伟冰又带来了一篇长文,详解了为什么 Redmi 要开启后性能时代?为什么选择和 MediaTek、Pixelworks 深度合作?以及后性
  • K60至尊版刚预热 一加Ace2 Pro正面硬刚

    K60至尊版刚预热 一加Ace2 Pro正面硬刚

    Redmi这边刚如火如荼的宣传了K60 Ultra的各种技术和硬件配置,作为竞品的一加也坐不住了。一加中国区总裁李杰发布了两条微博,表示在自家的一加Ace2上早就已经采用了和PixelWo
  • 红魔电竞平板评测:大屏幕硬实力

    红魔电竞平板评测:大屏幕硬实力

    前言:三年的疫情因为要上网课的原因激活了平板市场,如今网课的时代已经过去,大家的生活都恢复到了正轨,这也就意味着,真正考验平板电脑生存的环境来了。也就是面对着这种残酷的
  • 小米降噪蓝牙耳机Necklace分享:听一首歌 读懂一个故事

    小米降噪蓝牙耳机Necklace分享:听一首歌 读懂一个故事

    在今天下午的小米Civi 2新品发布会上,小米还带来了一款新的降噪蓝牙耳机Necklace,我们也在发布结束的第一时间给大家带来这款耳机的简单分享。现在大家能见到最多的蓝牙耳机
  • 谷歌KDD'23工作:如何提升推荐系统Ranking模型训练稳定性

    谷歌KDD'23工作:如何提升推荐系统Ranking模型训练稳定性

    谷歌在KDD 2023发表了一篇工作,探索了推荐系统ranking模型的训练稳定性问题,分析了造成训练稳定性存在问题的潜在原因,以及现有的一些提升模型稳定性方法的不足,并提出了一种新
  • 为什么你不应该使用Div作为可点击元素

    为什么你不应该使用Div作为可点击元素

    按钮是为任何网络应用程序提供交互性的最常见方式。但我们经常倾向于使用其他HTML元素,如 div span 等作为 clickable 元素。但通过这样做,我们错过了许多内置浏览器的功能。
  • 当家的盒马,加速谋生

    当家的盒马,加速谋生

    来源 | 价值星球Planet作者 | 归去来自己&ldquo;当家&rdquo;的盒马,开始加速谋生了。据盒马官微消息,盒马计划今年开放生鲜供应链,将其生鲜商品送往食堂。目前,盒马在上海已经与
  • OPPO K11采用全方位护眼屏:三大护眼能力减轻视觉疲劳

    OPPO K11采用全方位护眼屏:三大护眼能力减轻视觉疲劳

    日前OPPO官方宣布,全新的OPPO K11将于7月25日正式发布,将主打旗舰影像,和同档位竞品相比,其最大的卖点就是将配备索尼IMX890主摄,堪称是2000档位影像表
  • 苹果MacBook Pro 2021测试:仍不支持平滑滚动

    苹果MacBook Pro 2021测试:仍不支持平滑滚动

    据10月30日9to5 Mac 消息报道,苹果新的 14 英寸和 16 英寸 MacBook Pro 2021 上市后获得了不错的评价,亮点包括行业领先的性能,令人印象深刻的电池续航,精美丰
Top