I use v-for
to render the message list. when the first batch of messages are rendered, I use scrollIntoView()
on the newest one so the container scrolls to bottom. as the user scrolls up I fetch previous messages to create a seamless scroll.
the problem is that when new messages are rendered, the scroll goes to the top of the container.
I tried saving the first message id in the list before updating the list with fetched messages and then scrolling back to that message but it causes a jump on the screen for a moment and is not a good user experience.
how can I prepend and render older messages to the message list so that current messages stay in their place wherever they are on the screen?
message list is stores in vuex and I update it using this action:
HandleMessageList({state, commit}, msgList) {
const currentMessages = state.messages
const updatedMessages = msgList.concat(currentMessages)
commit('SET_MESSAGES', updatedMessages)
}
and in template:
<template>
<div class=msg-container" ref="messageDisplayArea">
<message-object
v-for="msg in msgList"
:key="msg.id"
/>
</div>
</template>
<script>
import {mapState} from "vuex";
export default {
name: "MessageDisplay",
components: {
MessageObject,
},
computed: {
mapState({
msgList: state => state.messages,
}),
},
updated() {
this.$nextTick(() => this.scrollToTarget())
},
mounted() {
this.$refs.messageDisplayArea.addEventListener('scroll', this.handleUserScroll)
},
beforeDestroy() {
this.$refs.messageDisplayArea.removeEventListener('scroll', this.handleUserScroll)
},
methods: {
scrollToTarget() {
// ... scroll back to the position before message list update
},
handleUserScroll(e) {
const scrollTop = e.target.scrollTop
const scrollHeight = e.target.scrollHeight
const elementHeight = e.target.offsetHeight
if (scrollTop === 0 && elementHeight < scrollHeight) {
// ... fetch older messages
}
},
},
}
</script>
versions:
vue 2.6.10
vuex 3.0.1
Advertisement
Answer
I found the behavior I wanted in this Quasar component
it is an infinite scroll component but the main part is that the scroll can be in reverse which is necessary for a chat message scroll.