原生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 第二课 操作包装集元素代码
Mar 14 Javascript
Prototype源码浅析 Enumerable部分之each方法
Jan 16 Javascript
通过js动态操作table(新增,删除相关列信息)
May 23 Javascript
JS根据生日算年龄的方法
May 05 Javascript
基于Jquery代码实现手风琴菜单
Nov 19 Javascript
js实现文字闪烁特效的方法
Dec 17 Javascript
浅谈js继承的实现及公有、私有、静态方法的书写
Oct 28 Javascript
js实现控制文件拖拽并获取拖拽内容功能
Feb 17 Javascript
基于vue实现web端超大数据量表格的卡顿解决
Apr 02 Javascript
vue路由切换时取消之前的所有请求操作
Sep 01 Javascript
js实现购物车商品数量加减
Sep 21 Javascript
vue实现拖拽交换位置
Apr 07 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
PHP Session 变量的使用方法详解与实例代码
2013/09/11 PHP
PHP读取RSS(Feed)简单实例
2014/06/12 PHP
PHP实现加密文本文件并限制特定页面的存取的效果
2016/10/21 PHP
php监测数据是否成功插入到Mysql数据库的方法
2016/11/25 PHP
PHP单例模式简单用法示例
2017/06/23 PHP
PHP+MySQL使用mysql_num_rows实现模糊查询图书信息功能
2018/05/31 PHP
从JavaScript的函数重名看其初始化方式
2007/03/08 Javascript
经典海量jQuery插件 大家可以收藏一下
2010/02/07 Javascript
由JavaScript中call()方法引发的对面向对象继承机制call的思考
2011/09/12 Javascript
js中判断Object、Array、Function等引用类型对象是否相等
2012/08/29 Javascript
jQuery插件开发精品教程让你的jQuery提升一个台阶
2016/01/27 Javascript
jQuery Validate插件实现表单验证
2016/08/19 Javascript
用jQuery实现可输入多选下拉组合框实例代码
2017/01/18 Javascript
微信小程序之滚动视图容器的实现方法
2017/09/26 Javascript
基于原生js实现判断元素是否有指定class名
2020/07/11 Javascript
使用eslint和githooks统一前端风格的技巧
2020/07/29 Javascript
antd日期选择器禁止选择当天之前的时间操作
2020/10/29 Javascript
python打开网页和暂停实例
2014/09/30 Python
Python无损音乐搜索引擎实现代码
2018/02/02 Python
python+pyqt5编写md5生成器
2019/03/18 Python
PyQt5 窗口切换与自定义对话框的实例
2019/06/20 Python
基于Python数据分析之pandas统计分析
2020/03/03 Python
python基于Kivy写一个图形桌面时钟程序
2021/01/28 Python
墨西哥皇宫度假村预订:Palace Resorts
2018/06/16 全球购物
乐高官方旗舰店:LEGO积木玩具
2019/04/06 全球购物
英国哈罗德园艺:Harrod Horticultural
2020/03/31 全球购物
环保专业大学生职业规划设计
2014/01/10 职场文书
小学防溺水制度
2014/01/29 职场文书
家电业务员岗位职责
2014/03/10 职场文书
亮剑观后感500字
2015/06/05 职场文书
2015年迎新晚会策划书
2015/07/16 职场文书
公司岗位说明书
2015/10/08 职场文书
小学2016年“我们的节日·重阳节”活动总结
2016/04/01 职场文书
nginx+lua单机上万并发的实现
2021/05/31 Servers
整理Python中常用的conda命令操作
2021/06/15 Python
Python常用配置文件ini、json、yaml读写总结
2021/07/09 Python