前言
根据项目需求,要给tab加上滚动的距离,但是偶尔会出现滚动不准确的原因,后来发现是因为图片还没加载完成之后,就提前计算了滚动距离,所以这次记录一下这次的问题及解决方案。
解决方案
等待所有图片上传成功之后,才去做某些操作。img
标签src
资源加载成功之后,会触发onload
事件,所以利用这个来看加载完之后和页面上的img
标签的数量是不是相等即可。
// 等待所有图片加载完成
waitingIamgesLoaded () {
let parents = document.getElementsByClassName('detailall')[0]
// 页面加载完成之后,获取页面上的img
let imgsList = [...parents.getElementsByTagName('img')]
let len = imgsList.length
// 图片加载完之后,就+1
let imgLoadedNum = 0
// console.log('获取当前页面所有图片数量', imgsList, len)
// 1. 页面没有图片时,直接去dosomething
if (imgsList.length === 0) {
this.getModuleOffsetTop()
console.log('页面没有图片,获取各个tab的滚动高度', this.moduleOffsetTop.join())
return
}
for (let i = 0; i < imgsList.length; i++) {
let e = imgsList[i]
/*
e.complete && e.naturalHeight != 0,这句是判断是否从缓存获取的图片资源
*/
let isLoaded = e.complete && e.naturalHeight != 0
console.log(`查看第${i + 1}张图片状态`, isLoaded)
// 2. 图片从缓存中获取
if (isLoaded) {
imgLoadedNum++;
// 全部图片被缓存
if (imgLoadedNum === len) {
this.getModuleOffsetTop()
console.log('图片被缓存下来,获取各个tab的滚动高度', this.moduleOffsetTop.join())
return
}
} else {
// 3. 图片从服务器获取
console.log('正在加载')
e.onload = () => {
// 全部从服务器获取
imgLoadedNum++;
console.log(`第${i + 1}张加载完成,${imgLoadedNum}`)
if (imgLoadedNum === len) {
this.getModuleOffsetTop()
console.log('图片从服务器上获取,获取各个tab的滚动高度', this.moduleOffsetTop.join())
return
}
}
}
}
},
// 获取各个模块的offsetTop,用来滚动
getModuleOffsetTop () {
console.log('获取滚动高度')
const modules = ['content', 'aboutUs', 'process']
this.moduleOffsetTop = modules.map((e) => {
// console.log('document.querySelector(`#${e}`).offsetTop', document.querySelector(`#${e}`).offsetTop)
return document.querySelector(`#${e}`).offsetTop - 80
})
},
注意: 经过测试,发现有以下需要注意的地方:
-
waitingIamgesLoaded
方法调用的时机,一定是DOM
渲染完之后才调用的,一般可以使用异步调用这个waitingIamgesLoaded
方法。 -
加载图片的方式,不是仅一种情况(从服务器获取资源),还有:
- 全部缓存读取
- 全部从服务器读取
- 部分从缓存读取,部分从服务器读取
- 部分图片从服务器读取资源失败,如果不监听img的error加载错误事件的话,上面写的
imgLoadedNum === len
条件永远不会执行!
所以,在
waitingIamgesLoade
方法里面,把前三种情况考虑进去。第4种情况,可以监听img图片加载错误时,拿一张默认图片进行替换。代码如下:< img :src="projectImg" @error="handleError($event)" />
handleError (e) { e.target.src = require('@/assets/image/default.png') },
最后
根据以上的方法,可以完美解决了滚动距离不准确的问题。后面可以优化成一个公共方法或者组件,下次再补充一下。