图片img懒加载实现原理方案懒加载优化用户体验

图片懒加载

在网站开发中,经常有一些页面需要加载大量图片,所以会有大量图片请求,性能优化之一就有较少网络请求要求,所以为了减轻浏览器负担,我们需要根据用户可视区域视角,内的图片才发起请求,在网页末尾端底部的图片,用户是还看不到的,所以暂时没有必要网络请求;

懒加载优点

  • 减轻浏览器负担,让内存先完成必须的工作
  • 减少网络请求
  • 较少并行时大量流量

实现关键逻辑:

  • 可视区域高度 window.innerHeight
  • img到顶部高度 getBoundingClientRect().top
  • 观察或监听 img到顶部距离是否小于可视区高度
  • img添加data-src默认属性 不设置src属性
  • 可加载图片: 离顶部高度 < 窗口可视区
  • 不加载图片: 离顶部高度 > 窗口可视区

代码实现

  • 方案一
const images = document.querySelectorAll("img")

window.addEventListener("scroll", () => {
    images.forEach(img => {
        const imgTop = img.getBoundingClientRect().top
        // 图片距离顶部高度 小于 可视区域高度
        if (imgTop < window.innerHeight) {
            img.setAttribute('src', img.getAttribute('data-src'))
        }
    });
})
  • 缺点:每次滚动条的滚动,会触发大量的事件,如果页面需要加载很多内容就会导致任务的堆积,而且就算图片全部加载完了,但是还是会继续执行事件,及时做了判断删除代理 removeEventListener 但是又要IE的兼容判断,繁琐得不要不要

  • 推荐最优方案new IntersectionObserver() 浏览器提供的观察者构造器,除了Internet其他主流浏览器都支持 详细文档

  • 方案二(最佳案例)
const images = document.querySelectorAll("img")

// 创建一个观察者 观察元素每次 出现可视区域交叉时候(看到了和划走了交叉)
const observer = new IntersectionObserver((entries = []) => {
    // 回调函数会触发2次,1:目标元素出现时触发, 2:元素看不见了触发
    entries.forEach(item => {
        // 观察到元素出现在可视区域
        if (item.isIntersecting) {
            const img = item.target
            img.setAttribute('src', img.getAttribute('data-src'))
            // 任务完成 关闭观察
            observer.unobserve(img)
        }
    })
})

images.forEach(image => {
    // 遍历每个img元素,并放入观察
    observer.observe(image);
})

用户体验

  • 以上就是懒加载方案实现了,当然这里并未结束,为了更好用户体验,我们可以给图片加载时错误时 进行期间默认图片,加入loading…,error图片
  • 继续深入体验优化:图片加载异常后,放一个重新加载功能,用户点击后,重新请求备案的src地址。
  • 一些即时通讯项目或者大量图片网站项目中 可以把图片按流量大小分次加载
    1. 例如按:默认(灰色) -> 模糊 -> 完整 -> 高清,等不同层级图片在不同时间完成渲染,合理浏览器渲染,就像生活避开高峰期,可以提前,或者拖后
    2. 例如微信聊天QQ,好友发来的图片第一时间一般都是模糊的,因为模糊图片流量更小,之后过几秒或者点击图片,才看到完整图片之内的优化

推荐插件

  • v-lazy vue插件
  • react-lazyload react插件

最后感谢

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值