原生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 27 Javascript
js取模(求余数)隔行变色
May 15 Javascript
Windows 系统下安装和部署Egret的开发环境
Jul 31 Javascript
浅谈利用JavaScript进行的DDoS攻击原理与防御
Jun 04 Javascript
axios post提交formdata的实例
Mar 16 Javascript
JavaScript实现淘宝京东6位数字支付密码效果
Aug 18 Javascript
vue2.0获取鼠标位置的方法
Sep 13 Javascript
JavaScript设计模式之观察者模式实例详解
Jan 16 Javascript
详解Vue中使用插槽(slot)、聚类插槽
Apr 12 Javascript
记一次react前端项目打包优化的方法
Mar 30 Javascript
vue 手机物理监听键+退出提示代码
Sep 09 Javascript
JS实现京东商品分类侧边栏
Dec 11 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 构造函数construct的前下划线是双的_
2009/12/08 PHP
php 实现301重定向跳转实例代码
2016/07/18 PHP
js控制框架刷新
2008/08/01 Javascript
JavaScript 异步调用框架 (Part 2 - 用例设计)
2009/08/03 Javascript
JS中判断null、undefined与NaN的方法
2014/03/24 Javascript
用jquery修复在iframe下的页面锚点失效问题
2014/08/22 Javascript
javascript实现给定半径求出圆的面积
2015/06/26 Javascript
Node.js的文件权限及读写flag详解
2016/10/11 Javascript
JS制作类似选项卡切换的年历
2016/12/03 Javascript
jQuery UI Grid 模态框中的表格实例代码
2017/04/01 jQuery
Vue组件通信的四种方式汇总
2018/02/08 Javascript
ES6 Iterator接口和for...of循环用法分析
2019/07/31 Javascript
详解利用nodejs对本地json文件进行增删改查
2019/09/20 NodeJs
JavaScript实现简单进度条效果
2020/03/25 Javascript
VUE子组件向父组件传值详解(含传多值及添加额外参数场景)
2020/09/01 Javascript
vue router返回到指定的路由的场景分析
2020/11/10 Javascript
简单了解Python下用于监视文件系统的pyinotify包
2015/11/13 Python
使用Kivy将python程序打包为apk文件
2017/07/29 Python
Python3 XML 获取雅虎天气的实现方法
2018/02/01 Python
pygame游戏之旅 游戏中添加显示文字
2018/11/20 Python
对web.py设置favicon.ico的方法详解
2018/12/04 Python
在python中实现强制关闭线程的示例
2019/01/22 Python
python 用 xlwings 库 生成图表的操作方法
2019/12/22 Python
selenium 多窗口切换的实现(windows)
2020/01/18 Python
用Python爬取LOL所有的英雄信息以及英雄皮肤的示例代码
2020/07/13 Python
Pytorch框架实现mnist手写库识别(与tensorflow对比)
2020/07/20 Python
详解使用postMessage解决iframe跨域通信问题
2019/11/01 HTML / CSS
Skyscanner波兰:廉价航班
2017/11/07 全球购物
《七颗钻石》教学反思
2014/02/28 职场文书
求职意向书范文
2014/04/01 职场文书
留学顾问岗位职责
2014/04/14 职场文书
体育系毕业生自荐信
2014/06/28 职场文书
单位作风建设自查报告
2014/10/23 职场文书
不同意离婚答辩状
2015/05/22 职场文书
React-vscode使用jsx语法的问题及解决方法
2021/06/21 Javascript
CSS中calc(100%-100px)不加空格不生效
2023/05/07 HTML / CSS