如何更快的显示页面?图片懒加载(附完整实现代码)引言 作为一名前端程序员,我们的天职是什么?我们的天职就是尽快的显示页面
引言
作为一名前端程序员,我们的天职是什么?我们的天职就是尽快的显示页面。如何能够更快的显示页面呢?这是我们程序员穷极一生想要达到的目标。今天就分享一个能够加快页面显示的技术:图片的懒加载技术。
渲染页面时,浏览器做了什么?
当浏览器要渲染一个页面时,主要经历了以下几个步骤:
- 下载html标签,将html标签解析成DOM树
- 下载css样式表,将多个CSS文件中的样式合并解析出具体树形结构(CSSOM树)。
- 合并DOM树和CSSOM树,生成渲染树
- 进行样式计算
- 布局并绘制
下面这张图可以看到其实浏览器要下载挺多的内容的。只有当他们全都下载完毕后才会进行下面的合成,计算等操作。
虽然说浏览器是多线程的,可以启动多个下载线程,但是一旦下载的内容多起来了,还是要进行排队等待。就好比高速公路一样,在平时高速公路很少出现堵车的现象,全程高速,但是一旦到放假的时候,高速公路就堵得不行。这个跟高速公路是一样的道理,虽然是多线程,但是终归还是有限的,当需要下载的东西多了,自然而然就要排队等候下载,此时页面就需要等所有的东西下载完才能加载出来。
怎样加快页面渲染——图片懒加载技术详解
什么是图片懒加载?
图片懒加载(Lazy Loading),又称为延迟加载或按需加载,是一种网页优化技术。它的核心思想是在页面初始化时,仅加载用户屏幕上可见区域的图像,而那些位于可视区域之外的图像则不会立即加载。当用户向下滚动页面,即将看到这些图片时,才动态地加载它们。
如下图,天猫超市的网站(上面显示出来的是首屏,下面没显示出来的是滚动后的页面)这个图要截快一点,不然就加载出来了!
如何实现图片懒加载?
我们通常情况下,使用<img src="4_img_jpg">
来直接添加图片,浏览器就会默认的立即加载src
属性指定的图片资源。要想实现懒加载的效果,我们就要阻止浏览器立即加载图片。所以我们可以将图片URL放在我们自定义的属性data-src
(数据属性)中,这样就可以防止图片在页面初始化时被加载。如图:
这样图片就显示不出来了!
如果我们想要图片显示出来,我们就得使用我们的JavaScript监测图片位置和页面滚动,判断图片何时进入可视范围。如果需要加载,再将data-src
中的URL赋值给src
,从而精确控制图片的加载时间。
具体的代码如下:
<script>
const imgs = document.getElementsByTagName("img");
const num = imgs.length;
let n = 0;
//解决不滚动就不能显示的问题
document.addEventListener("DOMContentLoaded",()=>{
loadImg()
})
function loadImg(){
console.log('hh');//测试监听的滚动事件
let screenHeight = document.documentElement.clientHeight;
// 应对不同浏览器的兼容性问题
let scrollTop = document.documentElement.scrollTop
|| document.body.scrollTop;
//检测图片是否进入可视区域,如果进入则将URL赋值给scr
for(let i = 0; i < num;i++){
if(imgs[i].offsetTop<screenHeight+scrollTop){
imgs[i].src = imgs[i].getAttribute('data-src')
n=i+1;
if(n===num){
//如果全部加载完后就可以移除掉滚动事件的监听
window.removeEventListener('scroll',throttleLelayLoad)
}
}
}
}
//减少滚动事件的触发次数
const throttleLelayLoad = _.throttle(loadImg,500)
window.addEventListener('scroll',throttleLelayLoad)
</script>
此时就可以滚到哪里就加载到哪里了
这个图片显示的不太好,大家可以自己去尝试一下!!!
总结
本篇文章粗略的讲述了一下页面渲染时浏览器的工作,以及如何实现页面懒加载。本文中重要的几个点分别是DOMContentLoaded
,scroll
,offsetTop
,removeEventListener
, _.throttle
大家可以分别深入了解一下这几个点的意思和作用,我也在代码中进行了相应的注释。如果还有不懂可以留言我们一起探讨一下!
完整实现代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
//common.css自己随便设置几个样式易于区分
<link rel="stylesheet" href="./common.css">
<script src="https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>
</head>
<body>
<img data-src="https://img.36krcdn.com/20190808/v2_1565254363234_img_jpg">
<img data-src="https://img.36krcdn.com/20190905/v2_1567641293753_img_png">
<img data-src="https://img.36krcdn.com/20190905/v2_1567640518658_img_png">
<img data-src="https://img.36krcdn.com/20190905/v2_1567642423719_img_000">
<img data-src="https://img.36krcdn.com/20190905/v2_1567642425030_img_000">
<img data-src="https://img.36krcdn.com/20190905/v2_1567642425101_img_000">
<img data-src="https://img.36krcdn.com/20190905/v2_1567642425061_img_000">
<img data-src="https://img.36krcdn.com/20190904/v2_1567591358070_img_jpg">
<img data-src="https://img.36krcdn.com/20190905/v2_1567641974410_img_000">
<img data-src="https://img.36krcdn.com/20190905/v2_1567641974454_img_000">
<script>
const imgs = document.getElementsByTagName("img");
const num = imgs.length;
let n = 0;
//dom树创建完成
document.addEventListener("DOMContentLoaded",()=>{
loadImg()
})
function loadImg(){
console.log('hh');
let screenHeight = document.documentElement.clientHeight;
// 不同浏览器的兼容性问题
let scrollTop = document.documentElement.scrollTop
|| document.body.scrollTop;
for(let i = 0; i < num;i++){
//console.log(imgs[i].offsetTop);
if(imgs[i].offsetTop<screenHeight+scrollTop){
imgs[i].src = imgs[i].getAttribute('data-src')
n=i+1;
if(n===num){
window.removeEventListener('scroll',throttleLelayLoad)
}
}
}
}
const throttleLelayLoad = _.throttle(loadImg,500)
window.addEventListener('scroll',throttleLelayLoad)
</script>
</body>
</html>
转载自:https://juejin.cn/post/7381396879057190953