Vue.js:图片懒加载和预加载的实现与原理
1、背景
我们在项目开发的时候经常会有图片展示,如有用户头像这类几KB的图片,也有照片、截图这类动则几MB的图片。对于几KB的图片加载速度是很快的,而几MB的图片在网速不佳时,那加载的时长会让你奔溃。
比如,你在浏览一系列图片的时候,如果要等所有图片都缓存到本地浏览器才可以看,那将会让你等很久。这就可以使用懒加载技术来帮助我们,让用户浏览图片时只加载前后几张图片,随着滑动浏览完再慢慢加载另外一批图片。在轮播图功能中也常需要这种技术。
再有另外一种场景,你想用一个img标签来动态切换显示图片,每次只显示一张照片,没有滑动的操作,如果在一个网速比较差的环境,图片显示完成后,切换src—请求加载—显示,这个时间就显得比较久,很影响用户体验。这时候就可以使用预加载技术来帮助我们,让显示当前图片时就开始请求加载下一张图片,等上张图片切换src后直接显示。
2、懒加载
2.1、实现
//1、安装插件:
npm install vue-lazyload --save-dev
//2、在main.js 中添加插件
import VueLazyLoad from 'vue-lazyload'
Vue.use(VueLazyLoad,{
error:'./static/error.png', //报错需要的图片
loading:'./static/loading.png'// 替换需要的图片
})
//3、将vue组件中img标签的:src=""属性修改为v-lazy=""
<img v-lazy="pictureSrcURL"/>
附上vue-lazyload的参考文档:https://www.npmjs.com/package/vue-lazyload
2.2、原理
懒加载的实现有两种方法:1)DOM元素的getBoundingClientRect方法;2)DOM元素的intersectionObserver方法。
1)getBoundingClientRect 方法能够返回当前DOM节点相关的css边框集合,其中有一个Top 属性代表当前DOM 节点距离浏览器窗口顶部的高度,只需判断top值是否小于当前浏览器窗口的高度(window.innerHeight),若小于说明已经进入用户视野,此时就能将loading状态的图片替换为真正的图片。
注意事项:
- 因为需要监听scroll 事件,不停的判断top 的值和浏览器高度的关系,所以需要对监听事件进行函数节流;
- 当屏幕首次渲染时,不会触发scroll 事件,需要主动调用一次事件处理程序,否则若用户不滚动则首屏的图片会一直使用懒加载的默认图片;
- 当所有需要懒加载的图片都被加载完,需要移除事件监听,避免不必要的内存占用。
2)intersectionObserver方法作为一个构造函数,需要传入一个回调函数作为参数,生成一个实例observer,这个实例有一个observe方法用来观察指定元素是否进入了用户的可视范围,随即触发传入构造函数中的回调函数。同时需要给回调函数传入一个entries 的参数,记录着这个实例观察的所有元素的对象,其中intersectionRatio 属性表示图片已经进入可视范围百分比,大于0 表示已经有部分进入了用户视野,此时就能将loading状态的图片替换为真正的图片,并且调用实例的unobtrusive方法将这个img 元素从这个实例的观察列表的去除,较第1种方法简便。
3、预加载
3.1、实现
export default {
data () {
return {
realPictureURL: ''
pictureURLList: [../aaa.png, ../bbb.png, ../ccc.png, ../ddd.png]
}
}
methods:{
//可以写一个setInterval函数,定时执行这个函数。
changePictureURL(idnex){
//1、创建一个img对象
let newImg = new Image();
//2、注意需要先定义好onload时间,再对img对象的src赋值
//否则无法触发onload函数
newImg.onload = () => {
this.realPictureURL = newImg.src;
}
newImg.src = this.pictureURLList[index];
}
}
}
3.2、原理
当image对象加载完图片之后会触发onload函数,在浏览器中加载完图片会自动放在缓存中,在一定时间内重复访问相同的url,首先会在浏览器的缓存中找,如果找不到的话,再根据url去访问服务器并缓存到浏览器中。
需要注意的是:
1)onload函数需要先定义,
2)再为image对象的src属性赋值。
如果把这两个步骤颠倒,虽然能加载到图片,但是无法触发到onload函数,最终使得预加载失败。
更多推荐
所有评论(0)