When you encounter a problem that is difficult to solve, adjust your attitude and change your way of thinking.
preface
The requirement scenario is as follows: Message sending is realized. If there are too many messages in the container, the scrollbar will appear. The latest message is located at the bottom and cannot appear in the visible area in time. Let’s take a look at the final result
Implementation approach
- After rendering the data, get the actual height of the message container from the Refs object
- Set the scroll bar to the bottom
The implementation process
sendMessage: function (event) {
// Data rendering
this.senderMessageList.push(thisSenderMessageObj);
// Change the scroll bar position
this.$nextTick(function(){
this.$refs.messagesContainer.scrollTop = this.$refs.messagesContainer.scrollHeight;
console.log("Current scrollbar position :"+this.$refs.messagesContainer.scrollTop);
console.log("Current scrollable area container height :"+this.$refs.messagesContainer.scrollHeight);
});
}
Copy the code
Record on pit
-
Sets the position of the scroll bar directly
After the data rendering is complete, get the real height of the element directly and set the position of the scrollbar. There seems to be nothing wrong with it, but the scrollbar height is not as expected. Vue has not yet rendered the DOM element after the data rendering is complete. The scrollbar height is set to the same container height as before.
sendMessage: function (event) { // Data rendering this.senderMessageList.push(thisSenderMessageObj); // Change the scroll bar position this.$refs.messagesContainer.scrollTop = this.$refs.messagesContainer.scrollHeight; console.log("Current scrollbar position :"+this.$refs.messagesContainer.scrollTop); console.log("Current scrollable area container height :"+this.$refs.messagesContainer.scrollHeight); } Copy the code
- Use setTimeout() to make DOM manipulation asynchronous (my solution).
this.messagesContainerTimer = setTimeout((a)= >{
this.$refs.messagesContainer.scrollTop = this.$refs.messagesContainer.scrollHeight;
console.log("Current scrollbar position :"+this.$refs.messagesContainer.scrollTop);
console.log("Current scrollable area container height :"+this.$refs.messagesContainer.scrollHeight);
// Clean up timer
clearTimeout(this.messagesContainerTimer);
},0);
Copy the code
-
Correct implementation: Use nextTick implementation
Thank you for pointing out the error in the comments section. Vue official has provided a ready-made solution. NextTick executes automatically when the data is updated and rendered in the DOM.
this.$nextTick(function(){ this.$refs.messagesContainer.scrollTop = this.$refs.messagesContainer.scrollHeight; console.log("Current scrollbar position :"+this.$refs.messagesContainer.scrollTop); console.log("Current scrollable area container height :"+this.$refs.messagesContainer.scrollHeight); }); Copy the code
Write in the last
- If there are any errors in this article, please correct them in the comments section. If this article helped you, please like it and follow 😊
- This article was first published in the Nuggets. If you need to reprint it, please leave a comment at 💌