原生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 相关文章推荐
jQuery实用基础超详细介绍
Apr 11 Javascript
js替换字符串的所有示例代码
Jul 23 Javascript
浅析JavaScript中的类型和对象
Nov 29 Javascript
将HTML格式的String转化为HTMLElement的实现方法
Aug 07 Javascript
zTree获取当前节点的下一级子节点数实例
Sep 05 Javascript
javaScript中的空值和假值
Dec 18 Javascript
深入理解JS的事件绑定、事件流模型
May 13 Javascript
vue better scroll 无法滚动的解决方法
Jun 07 Javascript
js实现前面自动补全位数的方法
Oct 10 Javascript
浅谈在Vue.js中如何实现时间转换指令
Jan 06 Javascript
ES6 Promise对象的含义和基本用法分析
Jun 14 Javascript
Node.js API详解之 readline模块用法详解
May 22 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
通过html表格发电子邮件
2006/10/09 PHP
解析如何修改phpmyadmin中的默认登陆超时时间
2013/06/25 PHP
PHP计算2点经纬度之间的距离代码
2013/08/12 PHP
解决file_get_contents无法请求https连接的方法
2013/12/17 PHP
总结PHP中DateTime的常用方法
2016/08/11 PHP
Yii框架表单提交验证功能分析
2017/01/07 PHP
PHP的JSON封装、转变及输出操作示例
2019/09/27 PHP
javascript instanceof,typeof的区别
2010/03/24 Javascript
jquery 学习之一 对象访问
2010/11/23 Javascript
JavaScript的类型、值和变量小结
2015/07/09 Javascript
JS表格组件神器bootstrap table详解(强化版)
2016/05/26 Javascript
jQuery代码性能优化的10种方法
2016/06/21 Javascript
Vue.js实战之利用vue-router实现跳转页面
2017/04/01 Javascript
vue使用axios实现文件上传进度的实时更新详解
2017/12/20 Javascript
Vue组件中prop属性使用说明实例代码详解
2018/05/31 Javascript
使用proxy实现一个更优雅的vue【推荐】
2018/06/19 Javascript
vue使用ElementUI时导航栏默认展开功能的实现
2018/07/04 Javascript
vue和H5 draggable实现拖拽并替换效果
2020/07/29 Javascript
vant 中van-list的用法说明
2020/11/11 Javascript
[13:40]TI3青蛙君全程回顾 DOTA2我们为梦想再战
2013/09/13 DOTA
python数据结构树和二叉树简介
2014/04/29 Python
Python最基本的数据类型以及对元组的介绍
2015/04/14 Python
深入理解Python中装饰器的用法
2016/06/28 Python
详解如何为eclipse安装合适版本的python插件pydev
2018/11/04 Python
PyTorch基本数据类型(一)
2019/05/22 Python
OpenCV里的imshow()和Matplotlib.pyplot的imshow()的实现
2019/11/25 Python
利用html5的websocket实现websocket聊天室
2013/12/12 HTML / CSS
HTML5未来发展趋势
2016/02/01 HTML / CSS
美国眼镜网站:EyeBuyDirect
2017/04/13 全球购物
跟单文员的岗位职责
2013/11/14 职场文书
女方婚礼新郎答谢词
2014/01/11 职场文书
财务总监管理岗位职责
2014/03/08 职场文书
物流管理系毕业生求职信
2014/06/03 职场文书
2014年妇委会工作总结
2014/12/10 职场文书
《我和小伙伴》教学反思
2016/02/20 职场文书
Go结合Gin导出Mysql数据到Excel表格
2022/08/05 Golang