簡體   English   中英

鼠標移動后無盡的while循環

[英]endless while loop after mousemove

我在這里瘋了。 我想在鼠標移動時顯示一個元素,並在鼠標最后一次移動10秒后將其隱藏。

我這樣寫:

document.addEventListener("DOMContentLoaded", function(event) {
  var time = 0;
  document.addEventListener("mousemove", function(event) {
    console.log('$');
    document.getElementsByClassName("mybar")[0].style.visibility = 'visible';
    time = 0;
    while (time < 11) {
      setTimeout(function() {
        time++
      }, 1000);
      console.log(time, time == 10);
      if (time == 10) {
        document.getElementsByClassName("mybar")[0].style.visibility = 'hidden';
      }
    }
  });
});
<div class='mybar'>
  <h1> TESTING </h1>
</div>

為什么會陷入無休止的循環? 為什么不按條件退出? 為什么if永遠不會獲得'true'參數? 注意 :請勿以這種方式運行它...它將殺死您的標簽頁。

首先,您無需等待DOMContentLoaded將事件偵聽器添加到document ,因為如果您這樣做了,則首先就不能添加DOMContentLoaded

無限循環是因為setTimeout不會暫停腳本。 它為您提供的時間安排回調,無論該時間如何,回調都不會運行,直到線程中當前正在運行的代碼完成為止,這永遠不會發生,因為您不會增加time變量。

因此循環永遠不會結束,因此線程永遠不會可用,因此回調永遠無法運行,因此time永遠不會增加。

最后,在共享局部變量並在諸如mousemove類的事件上非常快速地執行的事件處理程序中啟動setTimeout容易產生意外結果。 例如,在您的代碼中,每次處理程序運行時,它都會將time重置為0 ,這似乎並不是您想要的。


一種解決方案是放棄循環,安排可見性10秒鍾,並使用布爾變量防止處理程序中代碼的主要部分同時運行。

var timer = null;
document.addEventListener("mousemove", function(event) {
    var myBar = document.querySelector(".mybar");
    if (!myBar) {
      return; // there's no mybar element
    }


    if (timer == null) {
      myBar.style.visibility = 'visible';
    } else {
      clearTimeout(timer); // clear the currently running timer
    }

    // set to hidden in 10 seconds
    timer = setTimeout(function() {
      myBar.style.visibility = 'hidden';
      timer = null; // clear the timer
    }, 10000);
});

我還切換到了querySelector而不是getElementsByClassName因為它更短,更干凈。 而且我使用了一個變量來確保在設置樣式之前找到了元素。

您需要在mousemove范圍之外標記一個標志,該標志告訴偵聽器您已經運行了。

if(running) return; 
running = true;

在上下文中:

document.addEventListener("DOMContentLoaded", function(event) {
  var time = 0;
  var running = false;
  document.addEventListener("mousemove", function(event) {

    console.log('$');

    if(running) return;
    running = true;

    document.getElementsByClassName("mybar")[0].style.visibility = 'visible';
    time = 0;
    while (time < 11) {
      setTimeout(function() {
        time++
      }, 1000);
      console.log(time, time == 10);
      if (time == 10) {
        document.getElementsByClassName("mybar")[0].style.visibility = 'hidden';
      }
    }
  });
});

這是使用常規JavaScript的一種方法。 如果您的瀏覽器不符合ES6,則可以用正則函數表達式替換箭頭函數。 該示例在2秒而不是10秒后隱藏了文本,只是為了您可以看到它起作用而不必浪費8秒。

 //hide by default document.getElementById('myBar').style.display = 'none'; var timer = null; var hideDivTimer = () => { timer = setTimeout(() => { document.getElementById('myBar').style.display = 'none'; }, 2000); }; document.addEventListener('mousemove', () => { clearTimeout(timer); document.getElementById('myBar').style.display = 'inline'; hideDivTimer(); }); 
 <body> <div id='myBar'> <h1> TESTING </h1> </div> </body> 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM