懒加载使用场景
在一些图片量比较大的场景(电商首页,小程序首页等),如果我们打开页面时就加载所有的图片,那势必会导致页面的卡顿以及白屏,给用户不好的体验,导致用户流失。
但是我们仔细想一下,用户真的需要我们显示所有图片一起展示吗?其实并不是,用户看到的只是浏览器可视区域的内容。所以从这个情况我们可以做一些优化,只显示用户可视区域内的图片,当用户触发滚动的瞬间再去请求显示给用户。
懒加载的思路
一张图片就是一个标签,浏览器是否发起请求图片是根据的src属性,所以实现懒加载的关键就是,在图片没有进入可视区域时,先不给的src赋值,这样浏览器就不会发送请求了,等到图片进入可视区域再给src赋值
懒加载的问题
图片懒加载
- 只有进入(即将进入)可是区域的图片才进行加载
item.src = item.dataset.src
- 如果没有进入可视区域的图片不进行加载
问题1: 如果你希望实现图片懒加载, 那么渲染页面的时候, img 的 src 还能写吗 ?
- 不能
- 但是有需要直到该 img 标签应该引入的是哪一张图片
- 所以我们以一个自定义属性的形式, 来把该 img 需要的图片地址记录在标签身上
问题2: 获取元素img
- 不能在全局获取img
问题3: 当你第一次滚动的时候, 遍历所有图片,当你向下滚动的时候, 前面的图片已经加载过了,你再次遍历的时候还需要遍历吗 ? 不需要了
- 如果这个 img 标签已经有 src 属性了, 说明已经加载过了,就不需要判断高度了
if (item.src) return
图片什么时候进入可视区域
当scrollTop+clientHeight> offsetTop时候,可以加载新的图片了
加个50px,提前一点点距离加载新的图片
懒加载的实现
<ul>
</ul>
* {
margin: 0;
padding: 0;
}
li {
margin: 30px;
width: 340px;
height: 548px;
border: 2px solid #333;
}
img {
width: 100%;
height: 100%;
display: block;
}
var list = [{"id":625153951363,"name":"2020西太湖国际音乐节","showTime":"2020.09.19-09.20","price":"199-399","city":"常州","address":"常州西太湖中国花卉博览景区北门","pic":"https://img.alicdn.com/bao/uploaded/https://img.alicdn.com/imgextra/i3/2251059038/O1CN01zJEpaN2GdSG1Xvo8y_!!2251059038.jpg"},{"id":624506842658,"name":"2020舟山东海音乐节","showTime":"2020.09.04-09.06","price":"200-680","city":"舟山","address":"舟山市朱家尖南沙景区沙滩","pic":"https://img.alicdn.com/bao/uploaded/i4/2251059038/O1CN01L70FVl2GdSG2wpwyE_!!0-item_pic.jpg"},{"id":623216520608,"name":"中国•磐安 2020氧气山水音乐节","showTime":"2020.08.22 周六 16:30","price":"280","city":"金华","address":"金华磐安花溪风景区","pic":"https://img.alicdn.com/bao/uploaded/https://img.alicdn.com/imgextra/i3/2251059038/O1CN01ECp69h2GdSFpoUPAm_!!2251059038.jpg"},{"id":624345993344,"name":"2020“一生中最爱”七夕演唱会","showTime":"2020.08.25 周二 19:30","price":"180-580","city":"北京","address":"糖果TANGO-雍和宫店三层","pic":"https://img.alicdn.com/bao/uploaded/i3/2251059038/O1CN01WGNYBE2GdSFqXJgII_!!0-item_pic.jpg"},{"id":624170605605,"name":"东海五渔节之敢潮音乐节","showTime":"2020.08.22 周六 18:00","price":"198-228","city":"舟山","address":"舟山嵊泗五龙乡听海广场(原黄沙村船厂)","pic":"https://img.alicdn.com/bao/uploaded/https://img.alicdn.com/imgextra/i1/2251059038/O1CN01eV5pR32GdSFxJUb0v_!!2251059038.jpg"},{"id":624000957041,"name":"【聚光灯】周四周日爆笑脱口秀剧场","showTime":"2020.08.13-09.27","price":"99","city":"上海","address":"健力士醇黑坊","pic":"https://img.alicdn.com/bao/uploaded/i3/2251059038/O1CN01s9Jlz32GdSFv79hIO_!!0-item_pic.jpg"},{"id":623838540974,"name":"2020真世界摇滚演出","showTime":"2020.08.29 周六 20:30","price":"120","city":"北京","address":"糖果TANGO-雍和宫店三层","pic":"https://img.alicdn.com/bao/uploaded/i2/2251059038/O1CN01HWbQXk2GdSFxARpRD_!!0-item_pic.jpg"},{"id":624699066028,"name":"开心麻花首部悬疑惊悚喜剧《醉后赢家》","showTime":"2020.08.25-09.06","price":"80-1080","city":"北京","address":"地质礼堂剧场","pic":"https://img.alicdn.com/bao/uploaded/https://img.alicdn.com/imgextra/i2/2251059038/O1CN01Vv1mQO2GdSFvnmIDs_!!2251059038.png"},{"id":625219995330,"name":"开心麻花经典爆笑舞台剧《乌龙山伯爵》","showTime":"2020.08.25-08.30","price":"80-1080","city":"北京","address":"北京展览馆剧场","pic":"https://img.alicdn.com/bao/uploaded/i3/2251059038/O1CN01znXuKj2GdSG6ACMMb_!!0-item_pic.jpg"},{"id":623454281510,"name":"开心麻花重磅新戏《贼想得到你》","showTime":"2020.08.12 周三","price":"80-1280","city":"上海","address":"上汽上海文化广场","pic":"https://img.alicdn.com/bao/uploaded/i1/2251059038/O1CN013YAyeY2GdSFnXwgnQ_!!0-item_pic.jpg"},{"id":625314963280,"name":"开心麻花重磅新戏《贼想得到你》","showTime":"2020.08.15-08.21","price":"100-1180","city":"上海","address":"虹桥艺术中心","pic":"https://img.alicdn.com/bao/uploaded/i3/2251059038/O1CN01Qb8wyX2GdSG30DCl4_!!0-item_pic.jpg"},{"id":622815888793,"name":"开心麻花上海首部原创爆笑舞台剧《皇帝的新娘》","showTime":"2020.08.12-08.16","price":"80-1180","city":"上海","address":"上戏实验剧院","pic":"https://img.alicdn.com/bao/uploaded/i2/2251059038/O1CN01uie4Gf2GdSFlp1Rvv_!!0-item_pic.jpg"},{"id":624443634831,"name":"孟京辉戏剧作品《我爱xxx》","showTime":"2020.08.13-08.16","price":"100-380","city":"北京","address":"蜂巢剧场","pic":"https://img.alicdn.com/bao/uploaded/https://img.alicdn.com/imgextra/i3/2251059038/O1CN01LwdJRL2GdSFtDPtRL_!!2251059038.jpg"},{"id":624095704875,"name":"【8月8日-16日场次周年特惠低至四折】太阳马戏X绮幻之境 - 8月","showTime":"2020.08.12-08.30","price":"360-3460","city":"杭州","address":"杭州新天地太阳剧场","pic":"https://img.alicdn.com/bao/uploaded/i3/2251059038/O1CN01iyWOwU2GdSG2iMBsM_!!0-item_pic.jpg"},{"id":624163106935,"name":"高达5公里定向挑战赛","showTime":"2020.09.26 周六","price":"108-388","city":"上海","address":"世纪公园","pic":"https://img.alicdn.com/bao/uploaded/https://img.alicdn.com/imgextra/i3/2251059038/O1CN01y2n1PI2GdSFtLmEtu_!!2251059038.jpg"},{"id":622064265074,"name":"2020 FORMULA1 中国大奖赛(礼包&福袋)","showTime":"2020.07.04-12.31","price":"120-270","city":"上海","address":"上汽国际赛车场(上海国际赛车场)","pic":"https://img.alicdn.com/bao/uploaded/https://img.alicdn.com/imgextra/i2/2251059038/O1CN01ZHrnGM2GdSFbZjdUV_!!2251059038.jpg"},{"id":623662985515,"name":"2020ChinaJoy电竞赛事荟萃","showTime":"2020.07.31-10.30","price":"0","city":"北京","address":"请到大麦APP和优酷APP观看","pic":"https://img.alicdn.com/bao/uploaded/i4/2251059038/O1CN01RpgBQ82GdSFoMD7h8_!!0-item_pic.jpg"},{"id":618307700815,"name":"2020 FORMULA1 中国大奖赛(服装)","showTime":"2020.05.19-12.31","price":"248-620","city":"上海","address":"上汽国际赛车场(上海国际赛车场)","pic":"https://img.alicdn.com/bao/uploaded/i2/2251059038/O1CN01scI6Ly2GdSFEYDh7P_!!0-item_pic.jpg"},{"id":613334933912,"name":"2020 FORMULA1 中国大奖赛(周边衍生品)","showTime":"2020.03.11-12.31","price":"35-160","city":"上海","address":"上汽国际赛车场(上海国际赛车场)","pic":"https://img.alicdn.com/bao/uploaded/https://img.alicdn.com/imgextra/i3/2251059038/O1CN01ZusbUY2GdSENL0iIN_!!2251059038.jpg"},{"id":613323173822,"name":"2020 FORMULA1 中国大奖赛(帽品)","showTime":"2020.03.11-12.31","price":"200-335","city":"上海","address":"上汽国际赛车场(上海国际赛车场)","pic":"https://img.alicdn.com/bao/uploaded/https://img.alicdn.com/imgextra/i3/2251059038/O1CN01azreXu2GdSF9rIkGV_!!2251059038.jpg"},{"id":613940057617,"name":"加速北京跳伞俱乐部高空跳伞体验","showTime":"2020.08.05-08.31","price":"2980","city":"北京","address":"北京市平谷区马坊镇通航产业基地","pic":"https://img.alicdn.com/bao/uploaded/https://img.alicdn.com/imgextra/i1/2251059038/O1CN01Ns9MZj2GdSFIp2udB_!!2251059038.png"},{"id":624453755826,"name":"《你是演奏家2 · 超级金贝鼓》","showTime":"2020.08.21-08.23","price":"180-380","city":"上海","address":"美琪大戏院","pic":"https://img.alicdn.com/bao/uploaded/i4/2251059038/O1CN016u70M62GdSFrTL5GP_!!0-item_pic.jpg"},{"id":624211844323,"name":"正版授权·大型儿童实景舞台剧《奥特曼宇宙之光》","showTime":"2020.09.05 周六","price":"180-580","city":"海口","address":"海南省歌舞剧院","pic":"https://img.alicdn.com/bao/uploaded/https://img.alicdn.com/imgextra/i2/2251059038/O1CN01ybwkiZ2GdSFy9894v_!!2251059038.jpg"},{"id":624672730925,"name":"全国正版授权大型互动式儿童舞台剧 海底小纵队2—火山大冒险","showTime":"2020.11.15 周日","price":"80-480","city":"上海","address":"黄浦剧场-中剧场","pic":"https://img.alicdn.com/bao/uploaded/i1/2251059038/O1CN01mfDv5t2GdSFwbhzvt_!!0-item_pic.jpg"},{"id":624868314578,"name":"大船文化·加拿大原版音乐启蒙全场互动亲子剧《你是演奏家2·超级金贝鼓》","showTime":"2020.09.06 周日","price":"180-380","city":"天津","address":"津湾大剧院大剧场","pic":"https://img.alicdn.com/bao/uploaded/https://img.alicdn.com/imgextra/i4/2251059038/O1CN01l16ZUE2GdSFzGWSPx_!!2251059038.png"},{"id":624450522367,"name":"大船文化·法国艺术启蒙魔术剧《美术馆奇妙夜·星夜》中文版","showTime":"2020.09.06 周日","price":"120-280","city":"南京","address":"江苏大剧院--综艺厅","pic":"https://img.alicdn.com/bao/uploaded/i3/2251059038/O1CN01FMizHi2GdSG0AINxP_!!2-item_pic.png"},{"id":623125350409,"name":"大船文化 法国艺术启蒙魔术剧《美术馆奇妙夜·星夜》中文版","showTime":"2020.08.27-08.30","price":"80-480","city":"上海","address":"上汽上海文化广场","pic":"https://img.alicdn.com/bao/uploaded/https://img.alicdn.com/imgextra/i4/2251059038/O1CN01CiAVft2GdSFpIawAw_!!2251059038.jpg"},{"id":623975390263,"name":"正版授权大型实景舞台剧《奥特曼:宇宙之光》(杭州站)","showTime":"2020.12.13 周日","price":"68-480","city":"杭州","address":"杭州剧院","pic":"https://img.alicdn.com/bao/uploaded/https://img.alicdn.com/imgextra/i4/2251059038/O1CN01fUBSCY2GdSFsbnPPh_!!2251059038.jpg"}]
const ul = document.querySelector('ul')
bindHtml()
// 1. 渲染页面
function bindHtml() {
let str = ''
list.forEach(item => {
str += `<li><img data-src="${ item.pic }" alt=""></li>`
})
ul.innerHTML = str
// 只要渲染完毕页面, 执行 lazyload 图片懒加载
lazyload()
}
// 2. 实现图片懒加载
function lazyload() {
const imgs = ul.querySelectorAll('img')
// 2-1. 遍历拿到每一个 img
imgs.forEach(item => {
// 优化处理
// item 就是每一个 img 标签
// 如果这个 img 标签已经有 src 属性了, 说明已经加载过了,就不需要判断高度了
if (item.src) return
// 2-2. 拿到每一个图片距离顶部的尺寸
const img_top = item.offsetTop
const window_height = document.documentElement.clientHeight
const scroll_top = document.documentElement.scrollTop || document.body.scrollTop
// 2-3. 判断某一张图片进入页面了
if (img_top - 50 <= window_height + scroll_top) {
// 需要加载当前这一张图片了
item.src = item.dataset.src
}
})
}
// 要求 lazyload 随着浏览器的滚动随时执行
window.onscroll = function () {
lazyload()
}
参考: [前端性能优化-图片懒加载(防抖、节流)](https://juejin.cn/post/6844904035258990606)