Iwen's blog Iwen's blog
首页
  • 前端文章

    • JavaScript
    • Vue
  • 学习笔记

    • 《JavaScript教程》笔记
    • 《JavaScript高级程序设计》笔记
    • 《ES6 教程》笔记
    • 《Vue》笔记
    • 《TypeScript 从零实现 axios》
    • 小程序笔记
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • Linux
  • 学习
  • 面试
  • 心情杂货
  • 友情链接
  • 网站
  • 资源
  • Vue资源
  • 分类
  • 标签
  • 归档
复盘
关于

Iwen

不摸鱼的哥哥
首页
  • 前端文章

    • JavaScript
    • Vue
  • 学习笔记

    • 《JavaScript教程》笔记
    • 《JavaScript高级程序设计》笔记
    • 《ES6 教程》笔记
    • 《Vue》笔记
    • 《TypeScript 从零实现 axios》
    • 小程序笔记
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • Linux
  • 学习
  • 面试
  • 心情杂货
  • 友情链接
  • 网站
  • 资源
  • Vue资源
  • 分类
  • 标签
  • 归档
复盘
关于
  • Vue

  • Vue进阶

  • CSS

  • ES6

  • Base

  • Core

  • Array

  • Object

  • String

  • Async

  • Browser

  • Http

  • 性能优化

    • 节流防抖
    • 图片懒加载
      • clientHeight、scrollTop 和 offsetTop
      • getBoundingClientRect
      • IntersectionObserver
    • Script的加载和执行
    • 防抖多列表的骚操作
    • 渲染几万条数据不卡住页面
    • 前端性能优化总结
  • 正则

  • 经典总结

  • 设计模式

  • 数据结构

  • 算法

  • 手写

  • TypeScript

  • 复盘
  • 性能优化
Mr.w
2020-11-29

图片懒加载

# 图片懒加载

# clientHeight、scrollTop 和 offsetTop

首先给图片一个占位资源:

<img src="default.jpg" data-src="http://www.xxx.com/target.jpg" />
1

接着,通过监听 scroll 事件来判断图片是否到达视口:

let img = document.document.getElementsByTagName("img");
let count = 0;//计数器,从第一张图片开始计

lazyload();//首次加载别忘了显示图片

window.addEventListener('scroll', lazyload);

function lazyload() {
    let viewHeight = document.documentElement.clientHeight;//视口高度
    let scrollTop = document.documentElement.scrollTop || document.body.scrollTop;//滚动条卷去的高度
    for(let i = count; i < num; i++) {
        // 元素现在已经出现在视口中
        if(img[i].offsetTop < scrollHeight + viewHeight) {
            if(img[i].getAttribute("src") !== "default.jpg") continue;
            img[i].src = img[i].getAttribute("data-src");
            count ++;
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

当然,最好对 scroll 事件做节流处理,以免频繁触发:

// 调用节流方法
window.addEventListener('scroll', throttle(lazyload, 200));
1
2

# getBoundingClientRect

现在我们用另外一种方式来判断图片是否出现在了当前视口, 即 DOM 元素的 getBoundingClientRect API。

上述的 lazyload 函数改成下面这样:

function lazyload() {
    for(let i = count; i < num; i++) {
        // 元素现在已经出现在视口中
        if(img[i].getBoundingClientRect().top < document.documentElement.clientHeight) {
            if(img[i].getAttribute("src") !== "default.jpg") continue;
            img[i].src = img[i].getAttribute("data-src");
            count ++;
        }
    }
}
1
2
3
4
5
6
7
8
9
10

# IntersectionObserver

这是浏览器内置的一个API,实现了监听window的scroll事件、判断是否在视口中以及节流三大功能。

let img = document.document.getElementsByTagName("img");

const observer = new IntersectionObserver(changes => {
    //changes 是被观察的元素集合
    for(let i = 0, len = changes.length; i < len; i++) {
        let change = changes[i];
        // 通过这个属性判断是否在视口中
        if(change.isIntersecting) {
            const imgElement = change.target;
            imgElement.src = imgElement.getAttribute("data-src");
            observer.unobserve(imgElement);
        }
    }
})
observer.observe(img);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

这样就很方便地实现了图片懒加载,当然这个IntersectionObserver也可以用作其他资源的预加载,功能非常强大。

节流防抖
Script的加载和执行

← 节流防抖 Script的加载和执行→

最近更新
01
flex布局页面自适应滚动条问题
12-28
02
前后端分离开发请求接口跨域如何携带cookie的问题
12-28
03
怎么实现div长宽比固定width-height4比3
12-28
更多文章>
Theme by Vdoing | Copyright © 2017-2022 Iwen | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式