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 💌