原生JS实现图片懒加载之页面性能优化


Posted in Javascript onApril 26, 2019

在项目开发中,我们往往会遇到一个页面需要加载很多图片的情况。我们可以一次性加载全部的图片,但是考虑到用户有可能只浏览部分图片。所以我们需要对图片加载进行优化,只加载浏览器窗口内的图片,当用户滚动时,再加载更多的图片。这种加载图片的方式叫做图片懒加载,又叫做按需加载或图片的延时加载。这样做的好处是:1.可以加快页面首屏渲染的速度;2.节约用户的流量。

一.实现思路

1.图片img标签自定义一个属性data-src来存放真实的地址。

2.当滚动页面时,检查所有的img标签,判断是否出现在事业中,如果出现在视野中,继续进行判断,看齐是否被加载过了,如果没有加载,那就进行加载。

判断图片元素是否处于浏览器视野中的示意图(手绘):

原生JS实现图片懒加载之页面性能优化

二.根据思路完成代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>原生js实现图片懒加载</title>
 <style>
 *{
  margin: 0;
  padding: 0;
  box-sizing: border-box;
 }
 ul{
  overflow: hidden;
  list-style: none;
 }
 li{
  float: left;
  width: 50%;
  height: 200px;
  padding: 10px;
 }
 li img{
  display: inline-block;
  width: 100%;
  height: 100%;
 }
 </style>
</head>
<body>
<div class="container">
 <ul>
 <li><img src="http://cdn.jirengu.com/book.jirengu.com/img/1.jpg" alt="" data-src="http://cdn.jirengu.com/book.jirengu.com/img/1.jpg"></li>
 <li><img src="" alt="" data-src="http://cdn.jirengu.com/book.jirengu.com/img/2.jpg"></li>
 <li><img src="" alt="" data-src="http://cdn.jirengu.com/book.jirengu.com/img/3.jpg"></li>
 <li><img src="" alt="" data-src="http://cdn.jirengu.com/book.jirengu.com/img/4.jpg"></li>
 <li><img src="" alt="" data-src="http://cdn.jirengu.com/book.jirengu.com/img/5.jpg"></li>
 <li><img src="" alt="" data-src="http://cdn.jirengu.com/book.jirengu.com/img/6.jpg"></li>
 <li><img src="" alt="" data-src="http://cdn.jirengu.com/book.jirengu.com/img/7.jpg"></li>
 <li><img src="" alt="" data-src="http://cdn.jirengu.com/book.jirengu.com/img/8.jpg"></li>
 <li><img src="" alt="" data-src="http://cdn.jirengu.com/book.jirengu.com/img/9.jpg"></li>
 <li><img src="" alt="" data-src="http://cdn.jirengu.com/book.jirengu.com/img/10.jpg"></li>
 <li><img src="" alt="" data-src="http://cdn.jirengu.com/book.jirengu.com/img/11.jpg"></li>
 <li><img src="" alt="" data-src="http://cdn.jirengu.com/book.jirengu.com/img/12.jpg"></li>
 <li><img src="" alt="" data-src="http://cdn.jirengu.com/book.jirengu.com/img/13.jpg"></li>
 <li><img src="" alt="" data-src="http://cdn.jirengu.com/book.jirengu.com/img/14.jpg"></li>
 <li><img src="" alt="" data-src="http://cdn.jirengu.com/book.jirengu.com/img/15.jpg"></li>
 <li><img src="" alt="" data-src="http://cdn.jirengu.com/book.jirengu.com/img/16.jpg"></li>
 </ul>
</div>
<script>
 // window绑定滚动事件
 window.addEventListener('scroll',function(){
 // 遍历所有的img标签
 Array.prototype.slice.apply(document.getElementsByTagName('li')).forEach((li)=>{
  let img=li.getElementsByTagName('img')[0];
  // 判断当前img是否出现在了视野中
  // 判断当前img是否被加载过了
  if(checkShow(img) && !isLoaded(img)){
  loadImg(img);
  }
 })
 });

 // 判断img是否出现浏览器视野中
 function checkShow(img) {
 let scrollTop=document.documentElement.scrollTop; // 页面向上滚动的高度
 let windowHeight=window.innerHeight; //浏览器自身高度
 let offsetTop=img.offsetTop; //目标标签相对于document的高度
 return (offsetTop > scrollTop && offsetTop <(windowHeight + scrollTop));
 }

 // 判断是否已经加载过
 function isLoaded(img) {
 return img.getAttribute('src')===img.getAttribute('data-src');
 }

 // 加载图片
 function loadImg(img) {
 img.setAttribute('src',img.getAttribute('data-src'));
 }
</script>
</body>
</html>

好了,在浏览器中运行一下,第一次进页面如果不滚动滚轮的话什么也看不到,所以第一次进页面需要调用checkShow(),处于视野中的图片也加载出来。

在代码最后加上:

// 第一次进页面加载处于视野中的图片
 Array.prototype.slice.apply(document.getElementsByTagName('li')).forEach((li)=>{
 let img=li.getElementsByTagName('img')[0];
 // 判断当前img是否出现在了视野中
 // 判断当前img是否被加载过了
 if(checkShow(img) && !isLoaded(img)){
  loadImg(img);
 }
 })

此时我们发现判断加载视野中的图片代码存在重复,直接封装成一个新的方法lazyRenderImg();

// window绑定滚动事件
 window.addEventListener('scroll',function(){
 // 遍历所有的img标签
 lazyRenderImg();
 });

function lazyRenderImg(){
 Array.prototype.slice.apply(document.getElementsByTagName('li')).forEach((li)=>{
  let img=li.getElementsByTagName('img')[0];
  // 判断当前img是否出现在了视野中
  // 判断当前img是否被加载过了
  if(checkShow(img) && !isLoaded(img)){
  loadImg(img);
  }
 })
 }

 // 第一次进页面加载处于视野中的图片
 lazyRenderImg();

三.性能优化

问题:window.scroll 方法页面只要一滚动就会触发里面的方法,对性能影响很大

解决方法:当页面停止滚动的时候,再去执行页面中的方法,类似与函数节流(throttle)

Tips:函数节流:等时间间隔执行函数, 让一个函数不要执行得太频繁,减少一些过快的调用来节流。

// window绑定滚动事件
 let timer;
 window.addEventListener('scroll',function(){
 console.log('scroll')
 // 遍历所有的img标签
 if(timer){
  clearTimeout(timer)
 }
 timer=setTimeout(()=>{
  console.log('lazyRenderImg...');
  lazyRenderImg();
 },300);

通过打印的日志发现当滚动停止后才执行lazyRenderImg方法的,确实减少了不必要调用lazyRenderImg的次数。

原生JS实现图片懒加载之页面性能优化

  以上所述是小编给大家介绍的原生JS实现图片懒加载之页面性能优化,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

Javascript 相关文章推荐
JS 时间显示效果代码
Aug 23 Javascript
JavaScipt中的Math.ceil() 、Math.floor() 、Math.round() 三个函数的理解
Apr 29 Javascript
js显示时间 js显示最后修改时间
Jan 02 Javascript
javascript去掉前后空格的实例
Nov 07 Javascript
JavaScript 语言基础知识点总结(思维导图)
Nov 10 Javascript
jquery实现人性化的有选择性禁用鼠标右键
Jun 30 Javascript
jQuery实现的点赞随机数字显示动画效果(附在线演示与demo源码下载)
Dec 31 Javascript
jquery中实现时间戳与日期相互转换
Apr 12 Javascript
完美解决jQuery fancybox ie 无法显示关闭按钮的问题
Nov 29 Javascript
jquery animate动画持续运动的实例
Nov 29 jQuery
jQuery NProgress.js加载进度插件的简单使用方法
Jan 31 jQuery
vue 插件的方法代码详解
Jun 06 Javascript
vue请求本地自己编写的json文件的方法
Apr 25 #Javascript
vue中img src 动态加载本地json的图片路径写法
Apr 25 #Javascript
详解如何给React-Router添加路由页面切换时的过渡动画
Apr 25 #Javascript
vue项目中使用fetch的实现方法
Apr 25 #Javascript
详解vuejs2.0 select 动态绑定下拉框支持多选
Apr 25 #Javascript
微信小程序遍历Echarts图表实现多个饼图
Apr 25 #Javascript
在微信小程序中使用图表的方法示例
Apr 25 #Javascript
You might like
PHP中上传大体积文件时需要的设置
2006/10/09 PHP
一个严格的PHP Session会话超时时间设置方法
2014/06/10 PHP
php中字符集转换iconv函数使用总结
2014/10/11 PHP
Linux下安装PHP MSSQL扩展教程
2014/10/24 PHP
php连接oracle数据库的方法(测试成功)
2016/05/26 PHP
PHP导出带样式的Excel示例代码
2016/08/28 PHP
php简单截取字符串代码示例
2016/10/19 PHP
PHP实现的敏感词过滤方法示例
2019/03/06 PHP
PHP配合fiddler抓包抓取微信指数小程序数据的实现方法分析
2020/01/02 PHP
javascript入门·动态的时钟,显示完整的一些方法,新年倒计时
2007/10/01 Javascript
JavaScript入门教程(12) js对象化编程
2009/01/31 Javascript
javascript编码的几个方法详细介绍
2013/01/06 Javascript
checkbox设置复选框的只读效果不让用户勾选
2013/08/12 Javascript
JavaScript 垃圾回收机制分析
2013/10/10 Javascript
JS连接SQL数据库与ACCESS数据库的方法实例
2013/11/21 Javascript
Jquery实现自定义tooltip示例代码
2014/02/12 Javascript
jquery的ajax异步请求接收返回json数据实例
2014/06/16 Javascript
jstree创建无限分级树的方法【基于ajax动态创建子节点】
2016/10/25 Javascript
基于JavaScript实现窗口拖动效果
2017/01/18 Javascript
Vue.js实战之使用Vuex + axios发送请求详解
2017/04/04 Javascript
jQuery+ajax实现局部刷新的两种方法
2017/06/08 jQuery
JavaScript利用fetch实现异步请求的方法实例
2017/07/26 Javascript
初识 Vue.js 中的 *.Vue文件
2017/11/22 Javascript
你不可不知的Vue.js列表渲染详解
2019/10/01 Javascript
深入浅析vue全局环境变量和模式
2020/04/28 Javascript
Python编程之变量赋值操作实例分析
2017/07/24 Python
Python使用tkinter库实现文本显示用户输入功能示例
2018/05/30 Python
Python3 读、写Excel文件的操作方法
2018/10/20 Python
python实现彩色图转换成灰度图
2019/01/15 Python
Python自动化运维之Ansible定义主机与组规则操作详解
2019/06/13 Python
calendar在python3时间中常用函数举例详解
2020/11/18 Python
用python实现一个简单的验证码
2020/12/09 Python
ONLY德国官方在线商店:购买时尚女装
2017/09/21 全球购物
三八红旗手事迹材料
2014/12/26 职场文书
2015新生加入学生会自荐书
2015/03/24 职场文书
HTML页面中使两个div并排显示的实现
2022/05/15 HTML / CSS