js 图片懒加载-阿里云开发者社区

开发者社区> 浮生茹梦> 正文

js 图片懒加载

简介: javascript 中使用 IntersectionObserver API 实现图片惰性加载[懒加载](lazy load)。
+关注继续查看

网页开发时,常常需要了解某个元素是否进入了"视口"(viewport),即用户能不能看到它。最常见的需求就是图片的懒加载。

有时,我们希望某些静态资源(比如图片),只有用户向下滚动,它们进入视口时才加载,这样可以节省带宽,提高网页性能。这就叫做"惰性加载"。

传统方式(scroll)

传统的实现方法是,监听到 scroll 事件后,调用目标元素的 getBoundingClientRect() 方法,得到它对应于视口左上角的坐标,再判断是否在视口之内。这种方法的缺点是,由于 scroll 事件密集发生,计算量很大,容易造成性能问题。

let t;
// 监听滑动事件
$el.addEventListener('scroll', () => {
  clearTimeout(t);
  t = setTimeout(() => {
    let height = $el.getBoundingClientRect().height; // 滚动所在容器的可视高度
    let top = $el.scrollTop; // 滚动距离
    let end = height + top;
    let $lazyimgElem = $el.querySelector('img'); // 懒加载的图片节点
    let elemTop = $lazyimgElem.offsetTop - top;
    // 始终只加载在当前屏范围内的图片
    if (elemTop >= top && elemTop <= end) {
      $item.src = $item.getAttribute('lazy-src');
      $item.removeAttribute('lazy-src');
      if (elemTop <= end) {
        let imageSrc = $item.getAttribute('lazy-src');
        // 判断图片是否已经加载
        if (imageSrc != null) {
          $item.src = $item.getAttribute('lazy-src');
          $item.removeAttribute('lazy-src');
        }
      }
    }
  }, 100)
});

在这里面由于 scroll 事件是每次滚动都能触发所以,在我们的滑动事件里面有可能会频繁获取节点,判断节点是已经加载图片,这里只是获取一个图片,如果是一个列表,我们要获取更多的节点话,就会使的计算量很大,容易造成性能问题。使用下面的方法就能避免这个问题。

IntersectionObserver

目前有一个新的 IntersectionObserver API,可以自动"观察"元素是否可见。使用这个对象可以很方便简单的实现图片的懒加载。

// 获取所有的懒加载的图片元素
const $images = document.querySelectorAll('.image');

// 构建观察器
let observer = new IntersectionObserver((entries) => {
  for (let entry of entries) {
    /*
     * 检测节点是否可见,可以通过 isIntersecting 验证,布尔值
     * 如果目标元素与交叉区域观察者对象(intersection observer)的根相交,返回 true
     * 此时描述了变换到交叉时的状态; 
     * 如果返回 false, 那么可以由此判断,变换是从交叉状态到非交叉状态.
     * 同时也可以根据 intersectionRatio 验证
     * intersectionRatio:目标元素的可见比例
     * 即 intersectionRect 占 boundingClientRect 的比例
     * 完全可见时为1,完全不可见时小于等于0
     * 如果不可见,就返回:
     *   if (entry.intersectionRatio <= 0) return;
     */
    if (entry.isIntersecting === true) { // 检测节点是否可见
      // 处于交叉可见状态
      let $image = entry.target as HTMLImageElement;
      $image.src = $image.getAttribute('lazy-src') as string;
      $image.removeAttribute('lazy-src');
    }
  }
});

for (let i = 0, len = $images.length; i < len; i++) {
  // 往观察器列表注册观察元素
  observer.observe($images[i]);
}

参考:
阮一峰:IntersectionObserver API 使用教程

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
[译] 在 iOS Swift 中的懒加载变量
这篇文章解释了在 Swift 中懒加载变量是如何工作的,你必须对闭包有一些了解。
486 0
Fragment懒加载(二)
之前已经写了一篇关于懒加载的文章,那为什么还要重新写一次呢?因为那是很久之前写的,而且是引用别人的代码,最近我又用到了懒加载,但是我发现我看不懂之前写的文章,所以打算重写一次。
844 0
阿里云服务器端口号设置
阿里云服务器初级使用者可能面临的问题之一. 使用tomcat或者其他服务器软件设置端口号后,比如 一些不是默认的, mysql的 3306, mssql的1433,有时候打不开网页, 原因是没有在ecs安全组去设置这个端口号. 解决: 点击ecs下网络和安全下的安全组 在弹出的安全组中,如果没有就新建安全组,然后点击配置规则 最后如上图点击添加...或快速创建.   have fun!  将编程看作是一门艺术,而不单单是个技术。
4615 0
Android--Fragment 实现懒加载和不重复加载
版权声明:本文为博主原创文章,转载请标明出处。 https://blog.csdn.net/chaoyu168/article/details/79217223 基类: package fragment; import android.
1266 0
SpringMVC懒加载导致的问题一则
本文不讨论 Spring 的 @Autowired 懒加载(lazy-init)问题。 今天突然发现一个问题。 在Tomcat启动时,SpringMVC并没有加载,而是第一次请求到来时才进行加载。
1369 0
阿里云服务器远程登录用户名和密码的查询方法
阿里云服务器远程连接登录用户名和密码在哪查看?阿里云服务器默认密码是什么?云服务器系统不同默认用户名不同
846 0
【spring bean】spring中bean的懒加载和depends-on属性设置
项目结构如下:   ResourceBean.java代码: 1 package com.it.res; 2 3 import java.io.File; 4 import java.
814 0
+关注
浮生茹梦
前端开发(Vue、React)、NodeJS 开发(eggjs、fastify、koa2)、Java、Python
9
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
文娱运维技术
立即下载
《SaaS模式云原生数据仓库应用场景实践》
立即下载
《看见新力量:二》电子书
立即下载