简介
在最近的一个项目中,遇到了在一个页面需要加载很多张图片,但是用户基本上是移动网络,校园网络,
于是打算使用图片延迟加载技术。
注意,我的案例是在 `ul` `li` 中进行,没有使用 `img`, 我的图片是作为背景图片加载。
第一版
因为是第一次造轮子,所以还没有参考 jquery lazyload
思路
- 创建一个指令针对每个
li
元素。 - 在每个指令中监听
window
或者li
元素的parent
的scroll
事件。 - 判断每个
li
元素的offsetTop
值,与当前的滚动距离(scrollTop)和当前屏幕
(ul的绝对高度
)。 - 选择性的更新远程图片,并标注该图片已加载,不要重复加载远程图片。
代码实现
|
|
|
|
问题
在少量的图片时,效果还是很显著的。但是当图片一多时,卡顿非常明显。
分析
事件的重复监听。
很明显我们这里的每个
li
都会执行一个指令,每个指令都又重复监听scroll
事件。Dom 的多次查询和操作。
因为每个指令都监听了
scroll
事件,因此每次滚动都没批量级的查询dom和操作dom。
第二版
基于第一次的问题,做出了以下更改。
将指令针对父级节点,可以减少事件的监听。
减少
dom
的查询和操作。将背景图片地址绑定到
data-origin
属性上。
代码实现
|
|
|
|
效果表现
- 可以达到正常的
dom
在视窗中时,才被加载。 - 在一定数量级的图片时,不会有很明显的卡顿现象。
问题
- 无法针对
window
的scroll
事件。 - 当频繁切换界面时,一但浏览器禁用缓存,那么背景图片就会重新加载,造成资源浪费。
第三版
主要解决缓存问题.
前提
- 浏览器禁用了图片缓存。
- 有多个 pages 可以切换显示。
分析
缓存图片
将远程的图片,转换成
base64
存储到本地。动态将
图片base64
赋给li
元素的背景图片。需要解决的问题,因为图片转换成base64后,会有变成很多字符,全部展示在dom上,会很卡顿。
隐藏不可见区域的背景图片。
隐藏不在当前区域的图片。
代码实现
|
|
|
|
总结
经过这三版的延迟加载,要制作一个高效率的组件。一定要:
- 减少事件的重复监听
- 减少直接对dom的查询和操作。