开发背景
我们网站内的所有图片都是从上到下扫描渲染的,如果网速较慢的时候,图片由0到1的整个过程将会出现较长的耗时,且留有较长的空白时间,针对这一问题,起初我的做法通常都是使用一张占位图,但是真实图片替换占位图的过程会出现闪烁的现象,于是我使用了渐进加载图片的方式对项目进行了优化。
渐进加载的整体流程?
页面中的图片可以先加载一个图片的模糊轮廓(小图),随着图片加载时长的增加,图片会逐渐变得清晰。
这里我们需要注意几个问题:
- 如何使用户无感知的替换新老图片?
- 如果页面内需要渲染多个图片,那我们岂不是要多添加n个DOM?
实际开发
我们项目中图片均是通过oss存储的,所以小图可以通url+参数的形式获取。例如,http://image-demo.oss-cn-hang...,h_100,m_lfit 。如果使用的是别的链接均可自行替换
- 添加自定义指令,由于项目中多个地方均需使用,所以采用的是全局添加的形式。
import Vue from 'vue' const gradual = Vue.directive('gradual', { bind(el, binding) { instertDom(el, binding) }, }) export default gradual
- 项目中所有需要用到渐进加载的图片我们均可以先用小图替换。真实图片我们可以通过指令传值的形式发送出去。
文章图片
加载大小图片的对比
文章图片
文章图片
- 新图片的添加及模糊图片的替换
- 之前提到的问题一我们可以通过透明度由1变0的过渡效果,对模糊图片进行隐藏,其中使用的
filter:blur()
是为了保证模糊图片的像素化不会那么明显。 - 针对问题二,采用的是
img
标签的onload
事件,在判断大图加载完成后,先对原有DOM添加隐藏效果,然后通过设置定时器的方式删除原有DOM,这里的定时器delay
要大于等于过渡动画中的delay
,以保证过渡效果全部显示完成。
- 之前提到的问题一我们可以通过透明度由1变0的过渡效果,对模糊图片进行隐藏,其中使用的
.gradual .vague{
filter: blur(2px);
}.gradual img.gradual-hide_img {
opacity: 0;
animation: origin 1s ease;
}.gradual img.gradual-hide_img {
position: absolute;
left: 0;
top: 0;
}@keyframes origin {
0% {
transform: scale(1);
opacity: 1;
}
100% {
transform: scale(1.1);
opacity: 0;
}
}
js部分
const instertDom = (target, binding) => {
Vue.nextTick(() => {
const parent = target.parentNode
parent.classList.add('gradual')
target.classList.add('vague')
const newElement = document.createElement('img')
newElement.classList.add('origin')
// 要先写onload 再添加src
newElement.onload = () => {
target.classList.add('gradual-hide_img')
// 删除原DOM 定时器可以多设置点
setTimeout(() => {
target.remove()
}, 1500)
}
newElement.src = https://www.it610.com/article/binding.value.src
if (parent.lastChild === target) {
parent.appendChild(newElement)
} else {
parent.insertBefore(newElement, target.nextSibling)
}
})
}
文章图片
ps: Vue.nextTick()是一定要带的,以保证页面DOM全部加载完成。不然页面中的总结target.parentNode
会是null
渐进加载的整体流程可以归纳如下:
【自定义指令实现渐进加载图片】加载小图 -> 渲染 -> 加载大图 -> 判断大图加载完成 -> 小图添加消失过渡 -> 删除小图DOM。
推荐阅读
- vite+vue3+typescript+pnpm-workspace-monorepo 项目搭建记录
- 为啥我用Vue.use(axios)报错了!()
- ts 版 vue 之 vue-property-decorator
- vue中实现 ‘换肤 / 切换样式主题’ 功能的三种方式详解(干货)
- 北京丨蓝湖丨产品设计协同平台丨诚招前端工程师 30K—50K
- Vue源码理解(一)