问题描述
开始我模拟数据,每一秒一条消息 ,最新消息自动到底部,但是我想滚动滑轮,查看之前消息的时候,这个时候来新消息了,又到下面了
问题出现的环境背景及自己尝试过哪些方法
没有思路
相关代码
这是我目前的写法
watch: {
list() {
this.$nextTick(() => {
let msg = document.getElementById("chatContainer"); // 获取对象;
msg.scrollTop = msg.scrollHeight; // 滚动高度
});
}
你期待的结果是什么?实际看到的错误信息又是什么?
我想要实现,在我没滚动的时候,最新消息 还是滚动底部,当我滚动滑轮时候,消息正常更新 但是 不滚动到底部 当我不滚动过5秒 消息这个时候 滚动底部,
###添加滚轮事件,设置状态,在新消息来时判断该状态再决定是否滚动到底部
###定义定时器 timer;
监听消息 list,有新消息时this.timer = setTimeout(fn,5000)
5s后执行置底,同时监听滚动条滚动事件,如果滚动的话clearTimeout(this.timer)
取消置底操作;
不过正常像QQ聊天的话,通常你翻记录看消息时,然后5s不动滚动条也应该保持原来位置并在最底部提示有多少条新消息。(与底部距离定义一个区间,如果超过这个距离应该保持滚动条,如果小于这个距离置底)
###判断一下,如果当前滚动条在最下面,就滚动,如果不在最下面,就不滚。
###<template>
<div>
<div class="chat-container" ref="chat">
<div class="message" v-for="(chat, chatIndex) in list" :key="chatIndex">
{{ chat }}
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
list: [],
isScrolling: false,
setScrollStatus: undefined,
};
},
created() {
setInterval(() => {
this.list.push("一条新消息");
}, 1000);
},
mounted() {
this.$refs.chat.onwheel = (e) => {
clearTimeout(this.setScrollStatus);
this.isScrolling = true;
this.setScrollStatus = setTimeout(() => {
this.isScrolling = false;
}, 5000);
};
},
methods: {},
watch: {
list: {
handler(newVal) {
this.$nextTick(() => {
if (this.isScrolling) return;
this.$refs.chat.scrollTop = this.$refs.chat.scrollHeight;
});
},
},
},
};
</script>
<style scoped lang="less">
.chat-container {
width: 360px;
height: 500px;
margin: auto;
border: 1px solid red;
overflow: auto;
.message {
margin: 20px 0;
}
}
</style>
###
从逻辑上,这样判断更合理
最后一条消息 在可视范围内(即可见,部分可见也视为可见),自动下滚显示新消息###
最后一条消息 不在可视范围内(即不可见),不自动滚动
我采用的逻辑是 定义一个阈值,如果超过了就不自动滚动,没超过就自动滚动
自动滚动的逻辑要写多个
- 接收到他人消息(走阈值逻辑)
- 自己发送消息(强制滚动)
- 查看历史消息(保持滚动条位置),这里可以缩短条数