1.减少 HTTP 请求数量
在浏览器与服务器进行通信时,主要是通过 HTTP 进行通信。浏览器与服务器需要经过三次握手,每次握手需要花费大量时间。而且不同浏览器对资源文件并发请求数量有限(不同浏览器允许并发数),一旦 HTTP 请求数量达到一定数量,资源请求就存在等待状态,这是很致命的,因此减少 HTTP 的请求数量可以很大程度上对网站性能进行优化。
(1)懒加载
https://yq.aliyun.com/articles/255157
什么是懒加载
懒加载也叫延迟加载,指的是在长网页中延迟加载图像,是一种很好优化网页性能的方式。用户滚动到它们之前,可视区域外的图像不会加载。这与图像预加载相反,在长网页上使用延迟加载将使网页加载更快。在某些情况下,它还可以帮助减少服务器负载。常适用图片很多,页面很长的电商网站场景中。
为什么要用懒加载
能提升用户的体验,不妨设想下,用户打开像手机淘宝长页面的时候,如果页面上所有的图片都需要加载,由于图片数目较大,等待时间很长,用户难免会心生抱怨,这就严重影响用户体验。
减少无效资源的加载,这样能明显减少了服务器的压力和流量,也能够减小浏览器的负担。
防止并发加载的资源过多会阻塞js的加载,影响网站的正常使用。
懒加载的原理
首先将页面上的图片的 src 属性设为空字符串,而图片的真实路径则设置在data-original属性中, 当页面滚动的时候需要去监听scroll事件,在scroll事件的回调中,判断我们的懒加载的图片是否进入可视区域,如果图片在可视区内将图片的 src 属性设置为data-original 的值,这样就可以实现延迟加载。
图片懒加载
http请求
如果你学过计算机网络你就会知道,我们请求一个带有n张图片的html文件实际上会发送n+1次请求,因为在浏览器解析html的时候遇到了src,就会请求src后面的内容。
设想一下如果我们的页面有1000000张图片,那么如果等待这些图片响应成功并加载完时延是非常大的,而且图片的加载是同步的,加载时会阻塞浏览器继续向下解析,用户体验非常差。
那么我们可不可以让图片按需加载呢?当图片出现在可视区的时候再加载它而不是一开始就加载完全部图片。
template:
<div @scroll="lazyLoad" ref="lazy">
<img v-for="(src, index) in imgs" src="##" :dataSrc="src" :key="index">
<!--more img-->
</div>
改变图片src
监听最外层div的滚动事件,触发滚动时遍历图片检测图片位置,若在可视区内则显示
复制代码
loadImg() {
var img = this.$refs.lazy.getElementsByClassName("lazyImg");
// 已滚动高度+可视区高度
var top = this.$refs.lazy.scrollTop + this.$refs.lazy.clientHeight;
for(var i = 0; i < img.length; i++) {
if(img[i].offsetTop <= top) { // 在可视区内则显示图片
img[i].src = img[i].getAttribute("datasrc");
}
}
},
lazyLoad() {
this.loadImg();
}
以上就实现了一个图片懒加载
一个严重的问题:滚动过程中会不断触发lazyLoad对图片做一个遍历并判断,那么就会做无数次for循环,更可怕的是,修改一次src会发送一个请求,在滚动的时候我们的for循环每次都从头判断并修改src请求图片,那么请求次数可想而知。
函数防抖
如果在滚动过程中不断触发遍历并判断图片是否在可视区的监听事件,会耗费很大的性能,这里采用函数防抖:当用户停止滚动时统一遍历判断图片位置
debounce(fn) {
// 函数防抖:用户停止操作之后触发
clearTimeout(this.timer);
this.timer = setTimeout(() => {
fn();
}, 1000);
}
我们可以将加载图片的方法放在debounce中
lazyLoad() {
this.debounce(this.loadImg);
}
这样当用户滚动页面时,松开手才会执行loadImg来遍历判断图片位置。
又出现了一个问题:如果用户在滚动时从页面底部上拉到顶部一直没有松手,那么在这期间都不会执行loadImg,这意味着页面的图片都不会显示,非常影响用户体验
防抖优化
我们规定,若用户上拉高度大于500px那么就自动加载一次可视区内图片,这里我们用oldScrollTop记录上次上拉高度
lazyLoad() {
// 如果上拉距离大于500px则自动加载
if(this.$refs.lazy.scrollTop - this.oldScrollTop > 500) {
this.loadImg();
this.oldScrollTop = this.$refs.lazy.scrollTop; // 更新oldScrollTop
} else { // 如果向下拉但小于500px则防抖加载
this.debounce(this.loadImg);
}
}
下拉优化
当用户下拉的时候我们并不需要执行lazyLoad,因为我们之前的图片已经加载过了,所以可以修改一下lazyLoad
lazyLoad() {
// 如果上拉距离大于500px则自动加载
if(this.$refs.lazy.scrollTop - this.oldScrollTop > 500) {
this.loadImg();
this.oldScrollTop = this.$refs.lazy.scrollTop;
} else if(this.$refs.lazy.scrollTop - this.oldScrollTop < 0) { // 如果向下拉则不做操作
return ;
} else { // 如果向下拉但小于500px则防抖加载
this.debounce(this.loadImg);
}
}
减少遍历个数
最重要的优化已经做完了,但是还可以从一些小细节更加优化一下,我们的loadImg方法中每次都是从0号下标开始遍历检查图片,但是在用户上拉操作之后一部分图片已经被加载了,就不需要再次去检查了。
我们可以用一个变量len记录上一次被加载后的最后一个图片,然后修改一下loadImg
loadImg() {
var img = this.getImages();
var top = this.$refs.lazy.scrollTop + window.screen.height;
// 从len开始检查
for(var i = this.len; i < img.length; i++) {
if(img[i].offsetTop <= top) {
img[i].src = img[i].getAttribute("datasrc");
this.len = i; // 更新len
}
}
}
懒加载和预加载
懒加载的原理:
图片预加载:就是在网页全部加载之前,提前加载图片,当用户需要查看时可直接从本地缓存中渲染,以提供给用户更好的体验,减少等待的时间。
图片懒加载(缓载):延迟加载图片或符合某些条件时才加载某些图片。
懒加载的实现:
HTML部分:
<div class="box">
<h1>js懒加载</h1>
<div class="box">
<img src="" class="img" lazyload="true" data-original="http://pic.58pic.com/58pic/17/18/97/01U58PIC4Xr_1024.jpg">
<img src="" class="img" lazyload="true" data-original="http://pic.58pic.com/58pic/17/18/97/01U58PIC4Xr_1024.jpg">
<img src="" class="img" lazyload="true" data-original="http://pic.58pic.com/58pic/17/18/97/01U58PIC4Xr_1024.jpg">
<img src="" class="img" lazyload="true" data-original="http://pic.58pic.com/58pic/17/18/97/01U58PIC4Xr_1024.jpg">
<img src="" class="img" lazyload="true" data-original="http://pic.58pic.com/58pic/17/18/97/01U58PIC4Xr_1024.jpg">
<img src="" class="img" lazyload="true" data-original="http://pic.58pic.com/58pic/17/18/97/01U58PIC4Xr_1024.jpg">
<img src="" class="img" lazyload="true" data-original="http://pic.58pic.com/58pic/17/18/97/01U58PIC4Xr_1024.jpg">
<img src="" class="img" lazyload="true" data-original="http://pic.58pic.com/58pic/17/18/97/01U58PIC4Xr_1024.jpg">
<img src="" class="img" lazyload="true" data-original="http://pic.58pic.com/58pic/17/18/97/01U58PIC4Xr_1024.jpg">
</div>
</div>
JS部分:
window.onload = function () {
//获取当前浏览器的视口高度
var viewHeight = document.documentElement.clientHeight;
//鼠标滚动回调
function lazyload() {