原生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 相关文章推荐
关于JavaScript的面向对象和继承有利新手学习
Jan 11 Javascript
jquery及原生js获取select下拉框选中的值示例
Oct 25 Javascript
直接在JS里创建JSON数据然后遍历使用
Jul 25 Javascript
JavaScript sup方法入门实例(把字符串显示为上标)
Oct 20 Javascript
angularjs指令中的compile与link函数详解
Dec 06 Javascript
jQuery网页版打砖块小游戏源码分享
Aug 20 Javascript
深入浅析JavaScript中的constructor
Apr 19 Javascript
js 点击a标签 获取a的自定义属性方法
Nov 21 Javascript
Node错误处理笔记之挖坑系列教程
Jun 05 Javascript
微信小程序实现tab页面切换功能
Jul 13 Javascript
layui实现根据table数据判断按钮显示情况的方法
Sep 26 Javascript
Vue OpenLayer 为地图绘制风场效果
Apr 24 Vue.js
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
Window下PHP三种运行方式图文详解
2013/06/11 PHP
PHP批量上传图片的具体实现方法介绍.
2014/02/26 PHP
PHP输出两个数字中间有多少个回文数的方法
2015/03/23 PHP
php中namespace use用法实例分析
2016/01/22 PHP
JS中的public和private对象,即static修饰符
2012/01/18 Javascript
js弹出框轻量级插件jquery.boxy使用介绍
2013/01/15 Javascript
js获得鼠标的坐标值的方法
2013/03/13 Javascript
Select下拉框模糊查询功能实现代码
2016/07/22 Javascript
Bootstrap在线电子商务网站实战项目5
2016/10/14 Javascript
javascript 实现动态侧边栏实例详解
2016/11/11 Javascript
Angular2学习笔记——详解NgModule模块
2016/12/02 Javascript
node.js的事件机制
2017/02/08 Javascript
微信小程序基于slider组件动态修改标签透明度的方法示例
2017/12/04 Javascript
Node.js中DNS模块学习总结
2018/02/28 Javascript
使用ng-packagr打包Angular的方法示例
2018/09/21 Javascript
jQuery时间戳和日期相互转换操作示例
2018/12/07 jQuery
微信小程序日历弹窗选择器代码实例
2019/05/09 Javascript
生产制造追溯系统之在线打印功能
2019/06/03 Javascript
Vue 中使用富文本编译器wangEditor3的方法
2019/09/26 Javascript
Python正则表达式知识汇总
2017/09/22 Python
python实现微信自动回复及批量添加好友功能
2019/07/03 Python
Python中的单下划线和双下划线使用场景详解
2019/09/09 Python
如何基于pythonnet调用halcon脚本
2020/01/20 Python
浅谈Python程序的错误:变量未定义
2020/06/02 Python
python 6行代码制作月历生成器
2020/09/18 Python
美国女性运动零售品牌:Lady Foot Locker
2017/05/12 全球购物
某公司C#程序员面试题笔试题
2014/05/26 面试题
生产经理的自我评价分享
2013/11/07 职场文书
售后服务承诺书
2014/03/26 职场文书
元旦寄语大全
2014/04/10 职场文书
中学清明节活动总结
2014/07/04 职场文书
道路施工安全责任书
2014/07/24 职场文书
本科应届生求职信
2014/08/05 职场文书
初中班主任工作随笔
2015/08/15 职场文书
教你用Python爬取英雄联盟皮肤原画
2021/06/13 Python
python用海龟绘图写贪吃蛇游戏
2021/06/18 Python