Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to quickly append multiple lines to div (one at a time) and scroll to bottom using Vue?

I'd like to monitor the output log of a job that's run on my webserver by watching it in the browser. I'm using websockets to send the output of the job to a Vue element. The output is sent line by line and I'd like to append the newest line to the Vue element and scroll to the bottom of the div to emulate running tail -f on the job output file.

It works, but if the lines are sent rapidly the browser CPU usage goes very high and the page is very slow to render. In Chrome DevTools I can see my websockets messages coming in just fine in real time. So I'm obviously not efficiently adding each line to the Vue element.

What is a more efficient way to append text line by line to a vue element and continuously scroll to the bottom?

Or should I buffer the websocket messages and process several lines at once?

<div id="job_output_vue" class="wordwrap">
    <pre>{{text}}</pre>
</div>

<script>
    var logSocket = new WebSocket('wss://' + window.location.host + '/ws/jobOutput/');

    logSocket.onmessage = function (event) {
    data = JSON.parse(event.data)
    if (data.line!==undefined)
        {
        appLog.appendText(data.line);
        }
    }

    var appLog = new Vue({
            el: '#job_output_vue',
            data: {
            text: ""
        },
        methods:
        {
            appendText(newText) {
                this.text = this.text + newText;
                this.scrollToEnd();
                },
            scrollToEnd() {
                var container = this.$el;
                container.scrollTop=container.scrollHeight;
                }
        },
        mounted() {
            this.appendText("Loading...");
        },
        beforeDestroy() {
        },
        });
</script>
like image 904
Mark Avatar asked Nov 21 '25 04:11

Mark


1 Answers

I could be wrong, but I think the scrolling is the expensive operation here. Something you could try would be adding a watcher for the text property, and handle the scrolling there:

...
methods: {
  appendText(newText) {
    this.text = this.text + newText;
  },
  scrollToEnd() {
    var container = this.$el;
    container.scrollTop=container.scrollHeight;
  }
},
watch: {
  text() {
    this.scrollToEnd();
  }
},
mounted() {
  var vm = this;
  this.appendText("Loading...");
},

I haven't tried this out, but I'm curious to know if it is more performant than what you started with. Let me know if this works!

like image 50
Vince Avatar answered Nov 23 '25 21:11

Vince



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!