先写下标题,今晚写这个博客~
昨晚改项目BUG改的太晚了,实在没空写,只能放在今天写咯~
最近写的小项目正好遇到需要懒加载和函数节流,查了资料了解了一下原理。现在写个博客总结一下查找到的资料并简单用JS实现一下,以便以后查阅~
注:本文未没有介绍预加载与函数防抖,主要是暂时未遇上这两个需求,日后有机会再补充!
懒加载
什么是懒加载呢?
- 懒加载又称作延迟加载(英语:lazyload),通俗的说一下就是访问一个网页的时候,先把图片的路径换成固定的一张图让其先占好位置(即占位图)。当页面滚动到这张图片出现在页面可视区域内时立即设置图片的真实路径,这便是懒加载。
为什么要用懒加载呢?
- 简单来说是为了优化网页,加快网页载入速度。说具体一点呢就是页面里的内容实在太多了,比如随便打开淘宝、京东等网上商城的网页,页面往下滚你可以看到有非常多的图片,这些图片大小不一,有的几百k有的可能要1m了。如果当用户进入页面时将这些图片全部都展示出来,那可能耗时太长,用户等的黄花菜都凉了。。。
- 所以可以使用懒加载先展示在浏览器可视区域内的图片,加快页面载入速度~
那接下来我就简单用JS实现一下懒加载,代码如下:
// 先给页面内所有需要懒加载的图片赋予'lazyload'的类属性
// 然后把图片正确的地址放在'data-src'属性中,如<img data-src="http://xxx.jpg">
let images = document.querySelectorAll('.lazyload') // 查找所有包含lazyload类属性的标签
let imgs = [].slice.call(images) // images是一个伪数组(对象),将images转为真的数组
// let imgs = Arrary.from(images) 功能与上面一样,为ES6语法
let onscroll = function(){
if(imgs.length === 0){ return window.removeEventListener('scroll', onscroll)}
// 判断imgs这个数组是否为空,如果为空就代表页面内没有需要懒加载的图片,删除监听滚动的事件
imgs.filter( (img)=> { img.classList.contains('lazyload') })
// 过滤掉imgs数组中不包含类名为'lazyload'的标签
imgs.forEach((img)=>{
if(inViewport(img)){
loadImage(img) // 如果此图片出现在视口内就设置图片的真实路径
}
})
}
window.addEventListener('scroll', onscroll) // 监听滚动事件,当滚动时触发onscroll
window.dispatchEvent(new Event('scroll'))
// 这行代码作用是让浏览器自动执行一下滚动事件,因为如果载入页面时浏览器自动没有执行滚动事件,那么此时在视口内的图片都没有真实的图片地址
function inViewport(img){
let { top, left, bottom, right } = img.getBoundingClientRect()
// 调用getBoundingClientRect()这个API,读取当前图片上下左右各边距离视口顶部和视口左边的值,并赋值给相应变量(这里使用的是ES6语法)
let vpHeight = document.documentElement.clientHeight // 获取视口高度
let vpWidth = document.documentElement.clientWidth // 获取视口宽度
return (( top > 0 && top < vpHeight || bottom > 0 && bottom < vpHeight ) &&
(left > 0 && left < vpWidth || right > 0 && right < vpWidth ))
// 这行代码返回布尔值,图片在视口内返回true,不在视口内返回false
}
function loadImage(img){
let image = new Image()
// 创建一个image对象
image.src = img.dataset.src
// 读取img的'data-src'属性,将图片真实地址赋给image的src属性,相当于给浏览器缓存了这张真实的图片
image.onload = function(){
img.src = image.src
// 当浏览器加载缓存的图片时,将图片真实地址放到此img标签内,那此img标签的真实图片便可直接展示出来
img.classList.remove('lazyload') // 删除img标签的'lazyload'类属性
}
}
函数节流
什么是函数节流呢?
- 这里先说一下什么是节流:比如你家的水龙头开到最大档,那水龙头里的水会哗哗的流下来,但是如果你把水龙头拧紧直到水以水滴的形式流出,那你就会发现每隔一段时间才会有一滴水流出
- 函数节流(英语:throttle)也就是设定一个执行的周期,前一次调用动作到当前调用动作的时间间隔大于或等于设定的执行周期时就执行该动作(如果时间间隔小于设定的执行周期时,就等时间到达设定的执行周期再执行动作),然后进入下一个周期。
为什么要用函数节流呢?
- 主要是为了限制函数的执行频率,用于优化函数触发频率过高而导致响应速度跟不上触发频率,出现bug、延迟、卡顿等现象。
那接下来我就简单用JS实现一下函数节流,代码如下:
function throttle(func, wait){
// 设置一个名为throttle的函数,此函数可接受两个参数,一个参数为执行函数,另一个参数为执行周期
let prev, timer
// 声明两个变量,一个为前一次调用动作的时间,一个为计时器
return function fn(){
// 返回名为'fn'的函数
let curr = Date.now()
// 获取当前时间
let diff = curr - prev
// 获取前一次调用动作到当前调用动作的时间间隔
if(!prev || diff >= wait){
func()
// 如果调是第一次用动作或时间间隔大于等于执行周期,则执行所传入的函数
prev = curr // 将当前时间赋值给前一次调用动作的时间
}else if(diff < wait){
clearTimeout(timer) // 如果时间间隔小于执行周期(即在时间间隔内又触发了一次事件),就清空原先的定时器
timer = setTimeout(fn, wait - diff) // 设置一个新的定时器,等时间到达设定的执行周期再执行函数'fn'
}
}
}
结语:以上就是我根据查找的资料总结实现的懒加载与函数节流。如果其中有问题,麻烦在评论中指出。谢谢~