如果为真则设置超时,否则取消

Set timeout on if true, cancel it on else

因此,我在鼠标悬停/鼠标移出事件上调用此函数。首先(鼠标悬停)我用 'open' 参数调用它,然后(鼠标移开)用 'close' 参数调用它。

我想为覆盖显示添加延迟,并在超时到期前取消显示 'close' 调用的函数。

如果没有超时,函数会在鼠标移开时立即进入 'close' 分支,如果有超时事件,它不会 运行 if 直到超时结束,没有机会 window.clearTimeout(emgOverTimer); 发挥它的魔力。

function emgFluidOverlayShow(action, currentElement) {
    var $overlay = $('#emg-fluid-overlay');

    if (action == 'open') {
        var emgOverTimer = setTimeout(function() {
            $(currentElement).addClass('emg-fluid-bring-front');
            $overlay.addClass('emg-fluid-anim-overlay');
            $overlay.data('statuson', true);
        }, 1000);
    } 
    else if (action == 'close') {
        window.clearTimeout(emgOverTimer);
        console.log(1);
        $overlay.removeClass('emg-fluid-anim-overlay');
        $overlay.data('statuson', false);
        $('.emg-fluid-header').find('.emg-fluid-bring-front').removeClass('emg-fluid-bring-front');
    }
}

您的 emgOverTimer 变量是函数中的 local 变量,因此在后续调用该函数时,它自然是 不同的 上一次调用使用的变量。

将其移出到包含范围,以便所有 emgFluidOverlayShow 函数调用都使用相同的变量:

var emgOverTimer = 0;                                  // <=== Declaration
function emgFluidOverlayShow(action, currentElement) {
  var $overlay = $('#emg-fluid-overlay');

  if (action == 'open') {
   emgOverTimer = setTimeout(function() {              // <=== No `var` here
    $(currentElement).addClass('emg-fluid-bring-front');
    $overlay.addClass('emg-fluid-anim-overlay');
    $overlay.data('statuson', true);
   }, 1000);

  } else if (action == 'close') {
    window.clearTimeout(emgOverTimer);
    console.log(1);
    $overlay.removeClass('emg-fluid-anim-overlay');
    $overlay.data('statuson', false);
    $('.emg-fluid-header').find('.emg-fluid-bring-front').removeClass('emg-fluid-bring-front');
  }
}

我还会更新逻辑来处理多个 open 调用的情况,方法是在 if (action == 'open') 之后插入:

window.clearTimeout(imgOverTimer);

并在计时器回调中清除计时器句柄以及 close 情况:

imgOverTimer = 0;

总之:

var emgOverTimer = 0;
function emgFluidOverlayShow(action, currentElement) {
  var $overlay = $('#emg-fluid-overlay');

  if (action == 'open') {
   window.clearTimeout(emgOverTimer);
   emgOverTimer = setTimeout(function() {
    emgOverTimer = 0;
    $(currentElement).addClass('emg-fluid-bring-front');
    $overlay.addClass('emg-fluid-anim-overlay');
    $overlay.data('statuson', true);
   }, 1000);

  } else if (action == 'close') {
    window.clearTimeout(emgOverTimer);
    emgOverTimer = 0;
    console.log(1);
    $overlay.removeClass('emg-fluid-anim-overlay');
    $overlay.data('statuson', false);
    $('.emg-fluid-header').find('.emg-fluid-bring-front').removeClass('emg-fluid-bring-front');
  }
}

简化的实时示例:

// Scoping function so we don't create any globals
(function() {
  "use strict"; // Strict mode is almost always a good idea

  // Handlers to simulate calls to our function
  document.getElementById("btnOpen").onclick = function() {
    emgFluidOverlayShow('open');
  };
  document.getElementById("btnClose").onclick = function() {
    emgFluidOverlayShow('close');
  };
  
  // Timer handle
  var emgOverTimer = 0;
  
  // Function
  function emgFluidOverlayShow(action) {
    if (action == 'open') {
      clearTimeout(emgOverTimer);
      emgOverTimer = setTimeout(function() {
        emgOverTimer = 0;
        document.getElementById("overlay").style.display = "";
      }, 1000);
    } else if (action == 'close') {
      clearTimeout(emgOverTimer);
      emgOverTimer = 0;
        document.getElementById("overlay").style.display = "none";
    }
  }

})();
<input type="button" id="btnOpen" value="Open">
<input type="button" id="btnClose" value="Close">
<div id="overlay" style="display: none">I'm the overlay</div>

请注意,使用无效句柄调用 clearTimeout 是空操作,而 0 根据定义是无效句柄,因此我们不需要 clearTimeout 周围的守卫电话。 (当然,如果你愿意,你可以添加它们。)


旁注:除非您的代码隐藏了 window 变量,否则没有技术原因要在 setTimeout 前面加上 window. 前缀(您可能这样做是为了强调或类似) . windowsetTimeout 都是全局变量,JavaScript 引擎必须像查找 window 一样努力工作(例如,通过所有包含范围链接) =25=] 等等。