[Vuejs]-SetTimeout on a high volume data

0👍

Your example seems to operate the opposite way round to the original problem description (the timer is on showing not hiding) but I think I get what you mean.

As you suggest, the problem is that the timer callback is being called after the mouseleave event fires. So the red box does get hidden but shortly thereafter the timer fires and brings it back.

In the example below I have simply cancelled the timer using clearTimeout. In general it might be necessary to store an array of such timers, one for each element, but in this specific example I believe it only makes sense to have one timer active at once so I can get away without an array.

I also moved the initial population of showBox into data. There seemed no reason to use a created hook here.

There’s no need to copy the whole array each time, you can just use $set to set the value in the existing array. I haven’t changed that in my example.

I would also note that for this particular example you don’t need an array to hold all the showBox values. Only one red box can be visible at once so you only need a single property to hold the index of the currently visible box. I haven’t changed this in my example as I suspect your real use case is not as straight forward as this.

new Vue({
  el: '#app',

  methods: {
    handleMouseEnter(index) {
      this.currentTimer = setTimeout(() => {
        let showBox = [...this.showBox];
        showBox[index] = true;
        this.showBox = showBox;
      }, 500);
    },
    handleMouseLeave(index) {
      clearTimeout(this.currentTimer)
      let showBox = [...this.showBox];
      showBox[index] = false;
      this.showBox = showBox;
    }
  },
  data() {
    const showBox = [];

    for (let i = 0; i <= 2000; i++) {
      showBox[i] = false;
    }

    return {
      showBox
    };
  }
})
<script src="https://unpkg.com/vue@2.6.10/dist/vue.js"></script>

<div id="app">
  <ul v-for="x in 2000" :key="x">
    <li @mouseenter="handleMouseEnter(x)" @mouseleave="handleMouseLeave(x)" style="height: 50px;">
      Hello
      <span style="background-color: red" v-show="showBox[x]">BOX</span>
    </li>
  </ul>
</div>

Leave a comment