At the beginning, I simulated the data, one message per second, and the latest message was automatically sent to the bottom. But I want to scroll the pulley to check the previous message. At this time, the new message came, and then it came to the bottom
No idea
This is how I write it now
watch: {
list() {
this.$nextTick(() => {
let msg = document.getElementById("chatContainer"); // 获取对象;
msg.scrollTop = msg.scrollHeight; // 滚动高度
});
}
I want to realize that when I don't scroll, the latest message will still scroll to the bottom. When I scroll the pulley, the message will be updated normally but will not scroll to the bottom. When I don't scroll for 5 seconds, the message will scroll to the bottom,
Add a scroll wheel event, set the status, judge the status when a new message comes, and then decide whether to scroll to the bottom
Define timer; Listen to the message list, when there is a new message this.timer =After 5 seconds of setTimeout (FN, 5000), set the bottom and monitor the scrolling events of the scroll bar. If scrolling, cleartimeout will be executed( this.timer )Cancel the bottom setting operation;
But normally, like QQ chat, usually when you look at the message through the record, and then the 5S fixed scroll bar should also keep the original position and prompt how many new messages there are at the bottom( Define an interval from the bottom. If the distance exceeds, the scroll bar should be kept. If the distance is less than, the scroll bar should be set at the bottom.)
If the current scroll bar is at the bottom, it will scroll. If it is not at the bottom, it will not scroll.
Click test codepen
<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>
Logically, this is more reasonable
If the last message is visible (that is, visible or partially visible), it will scroll down automatically to display the new message. If the last message is not visible, it will not scroll automatically
The logic I use is to define a threshold value. If it exceeds, it will not scroll automatically. If it doesn't exceed, it will scroll automatically
The logic of automatic scrolling needs to write multiple