场景:我们有个聊天室,进入聊天室的话我们的需求是,进入聊天室,滚动到最新信息底部,如果是文字的话,很简单,异步获取数据,然后设置滚动高度即可,我们的使用的是VUE,我们先来操作一下:
<template>
<div>
<div id="service">
<!-- 此处为聊天框内容-->
</div>
</div>
</template>
<script>
export default {
data() {
return {
msgData: [], //
}
},
created() {
this.getData();
},
methods() {
getData() {
getMsgApi().then(res => { // 这里axios封装好了,这里只提供一个例子,代表从后端获取信息数据
if(res.code == 0) { // 代表请求数据成功
this.msgData = res.data;
var dom = document.getElementById("service");
dom.scrollTop = dom.scrollHeight; // 滚动到底部
}
})
}
}
}
</script>
如果你的聊天室里面就只有文字的话,上面的代码就能很好的解决了滚动到底部的需求,但是聊天室不光只发文字,还得发图片,而图片有什么问题?图片是要加载的,是要时间的,你可以把图片的加载看成是异步的,所以你通过dom.scrollHeight获取的高度是不准确的,这个高度不是最终等所有图片加载完的高度,所以导致的效果就是你滚动不到最底部,所以这就是问题所在。
解决方法:
思路:你可以等所有图片加载完再计算滚动高度,这不就解决了吗?
<template>
<div>
<div id="service">
<!-- 此处为聊天框内容-->
</div>
</div>
</template>
<script>
export default {
data() {
return {
msgData: [], //
}
},
created() {
this.getData();
},
methods() {
getData() {
getMsgApi().then(res => { // 这里axios封装好了,这里只提供一个例子,代表从后端获取信息数据
if(res.code == 0) { // 代表请求数据成功
this.msgData = res.data;
this.$nextTick(() => {
this.imgLoad();
})
}
})
},
imgLoad() {
// 图片加载
if (document.readyState === "complete") { // complete代表文档加载完成
let images =
document.getElementsByClassName("item-leftimg");// 获取所有聊天图片dom
// 这里的images一定是要<img />的dom哦
const promises = Array.prototype.slice
.call(images)
.map((node) => {
return new Promise((resolve, reject) => {
let loadImg = new Image();
loadImg.src = node.src;
loadImg.onload = () => {
resolve(node);
};
});
});
Promise.all(promises).then((results) => { // 解决图片在加载中滚动条滚动不到底部的问题
var dom = document.getElementById("service");
dom.scrollTop = dom.scrollHeight;
});
}
}
}
}
</script>
上面使用到的Promise.all,Promise.all是所有的Promise都resolve之后才会执行then里面的方法
。如果你觉得这样虽然最终实现了但是会跳动,用户体验不好,你可以给页面加个loading不就体验好点了吗