setTimeout处理大量数据

时间:2019-12-18 15:34:44

标签: javascript vue.js

我已经尝试使用谷歌搜索和搜索整个堆栈溢出问题,但是我认为它归结为我用来搜索的关键字。

基本上,我的问题归结为以下问题:when the cursor leaves an element, wait 500 milliseconds before closing the element. Before close the element, check if the cursor is back in the element, and if its not, do not hide it

我正在使用vuejs来做到这一点,但我将问题归结为使用setTimeout函数。我拥有代码的部分相当复杂,无法在此处发布,因此我创建了一个简单的POC来演示问题:

<template>
  <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>
</template>

<script>
export default {
  name: "App",
  components: {},
  methods: {
    handleMouseEnter(index) {
      setTimeout(() => {
        let showBox = [...this.showBox];
        showBox[index] = true;
        this.showBox = showBox;
      }, 500);
    },
    handleMouseLeave(index) {
      let showBox = [...this.showBox];
      showBox[index] = false;
      this.showBox = showBox;
    }
  },
  data() {
    return {
      showBox: []
    };
  },
  created() {
    for (let i = 0; i <= 2000; i++) {
      this.showBox[i] = false;
    }
  }
};
</script>

您可以在此处签出沙箱:https://codesandbox.io/s/cold-river-ruz7b

如果以中等速度从上到下悬停,您将意识到即使离开li元素,红色框仍会保留。

我猜问题在于,handleMouseEntersetTimeout调用而handleMouseLeave没有被调用。因此,使handleMouseEnterhandleMouseLeave之后执行,从而显示该框。

在这里,任何观点都会受到高度赞赏,并且如果可以对造成问题的原因给出简短的解释,那将是很好的

1 个答案:

答案 0 :(得分:0)

您的示例似乎与原始问题描述相反(计时器正在显示未隐藏),但是我想我明白您的意思。

正如您所建议的那样,问题在于mouseleave事件触发后,将调用计时器回调。因此,红色方框的确被隐藏了,但是此后不久,计时器便触发并将其重新带回。

在下面的示例中,我仅使用clearTimeout取消了计时器。通常,可能需要存储一个这样的计时器数组,每个元素一个,但是在此特定示例中,我认为一次激活一个计时器才有意义,这样我就可以不用数组了。

我还将最初的showBox人口移到了data中。似乎没有理由在此处使用created钩子。

不需要每次都复制整个数组,只需使用$set即可在现有数组中设置值。在我的示例中,我没有更改。

我还要注意,对于这个特定示例,您不需要一个数组来保存所有showBox值。一次只能看到一个红色框,因此您只需要一个属性即可保存当前可见框的索引。在我的示例中,我没有改变这一点,因为我怀疑您的实际用例并不像这样简单。

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>