ACB
ACB

Reputation: 1637

vue large lists with autoscroll

I want to have an autoscrolling log on my page. The log gets dynamically polled from a REST endpoint. The problem now is that this log can get very large so I used vue-virtual-scroll-list to display the log. I also want the log to automatically scroll to the bottom unless I scrolled upwards at which point I want to keep the scroll position. For that I used vue-chat-scroll. The problem now is that the log scroll works fine in the beginning but after a few hundred entries the scrollbar gets completely messed up and not matching the content anymore and also not autoscrolling to the bottom. The vue component I wrote looks like this:

Vue.component('log', {
  data: function() {
    return { msgs: [] }
  },

  props: {
    id: { type: String, required: true },
    length: { type: Number, required: true },
    refreshRate: { type: Number, default: 1000 }
  },

  template: 
      '<virtual-list :size="40" :remain="length" class="list-unstyled" :ref="id" v-chat-scroll="{always: false}">\
        <li v-for="msg in msgs" :key="msg.id" :class="logColor(msg.severity)">\
          <pre>[{{ shortTimestamp(msg.timestamp) }}]: {{ msg.message }}</pre>\
        </li>\
      </virtual-list>',

  methods: {
    fetchLogs: function(){
      var session = this.id;
      var start = -this.length;
      if (this.msgs.length > 0)
        start = this.msgs[this.msgs.length - 1].id;

      var vue = this;
      $.post(getUrl("/sessions/" + session + "/log"), JSON.stringify({
        start: start
      })).then(function(data) {
        for(var msg of data){
          vue.msgs.push(msg);
        }
      });
    },

    shortTimestamp: function(time) {
      var fulldate = new Date(time);
      return fulldate.toLocaleTimeString();
    },

    logColor: function(severity) {
      switch (severity) {
        case "Trace":
          return "list-group-item-light";
        case "Debug":
          return "list-group-item-dark";
        case "Information":
          return "list-group-item-info";
        case "Notice":
          return "list-group-item-primary";
        case "Warning":
          return "list-group-item-warning";
        case "Error":
          return "list-group-item-danger";
        case "Critical":
          return "list-group-item-danger";
        case "Fatal":
          return "list-group-item-danger";
      }
    }
  },

  mounted: function() {
    setInterval(function () {
      this.fetchLogs();
    }.bind(this), this.refreshRate); 
  }
})

Is there any way to fix this?

Upvotes: 0

Views: 1382

Answers (1)

wang
wang

Reputation: 116

I think using Vuescroll may solve your problem.

  • First of all, Vuescroll has handle-resize event that can help you detect the size change of content and react to you.
  • Second, Vuescroll has scrollTo Api that can help you scroll to any location of the page.
  • Finally, but how do you solve the problem of too much data? OK, You can manually tailor the array of your data by listening handle-scroll event according to your own needs.

Upvotes: 1

Related Questions