因潜在扩展而过期的 Javascript 警报

标签 javascript jquery html css

我出现了 javascript 警报,我希望每个警报在 3 秒后消失,但是我只能让它们立即全部消失,然后我就无法再发出警报了。

我还希望,如果用户将鼠标悬停在警报上,这会重置 3 秒,直到警报消失。

现在我正在使用 setTimeout 函数,并且我 99% 确定这是我的问题,我认为我需要重构一些东西以使用一些 jquery 延迟或其他等待函数,但是我不确定如何做到这一点并仍然获得我正在寻找的行为。

HTML 看起来像这样:

<div id="site">
  <div class="btn btn-danger">Red Alert!</div>
  <div id="alerts" data-count="1">
  </div>
</div>

JavaScript 代码是:

$('.btn-danger').click(function(){
  var count = $('#alerts').data('count');
  var alert = '<div class="alert alert-danger" role="alert" data-dismiss="alert">' + count +'</div>';
  var a = $('#alerts').append(alert)
  setTimeout(function() { $(a).hide(); }, 3000);
  count += 1;
  $('#alerts').data('count', count);
});

JSFiddle

Final JSFiddle

最佳答案

所有警报立即消失并且您无法添加新警报的原因是以下代码:

var alert = '<div class="alert alert-danger" role="alert" data-dismiss="alert">' + count +'</div>';
var a = $('#alerts').append(alert)
setTimeout(function() { $(a).hide(); }, 3000);

您期望变量 a 是单个警报的 jQuery 对象,但事实并非如此。它是整个 $('#alerts') 对象,即警报的。这是因为 .append() 返回您要附加的对象,而不是您要附加的对象。换句话说,像许多 jQuery 函数一样,.append() 返回“点左边的东西”,因此它是可链接的。

因此,当计时器耗尽时,您不仅隐藏了单个警报,还隐藏了父容器,从而隐藏了所有警报。此后您的代码仍然可以成功创建警报元素,但您看不到它们,因为父级已隐藏。

我会做的是在开始时通过将 HTML 字符串包装在 $() 调用中来创建您想要的 jQuery 对象。我们将调用该变量$alert。当我们这样做时,由于 $('#alerts') 出现在代码中的多个位置,我们也会给它一个变量:

$('.btn-danger').click(function(){
  var $alerts = $('#alerts');
  var count = $alerts.data('count');
  var $alert = $(
    '<div class="alert alert-danger" role="alert" data-dismiss="alert">' +
      count +
    '</div>'
  );
  $alerts.append($alert);
  setTimeout(function() { $alert.hide(); }, 3000);
  count += 1;
  $alerts.data('count', count);
});

这是一个updated fiddle .

要在鼠标移到某个警报上时重置超时,您只需将 setTimeout() 返回值保存在本地变量中,并且当发生 mousemove 事件,对该变量调用 clearTimeout() 并启动一个新的计时器,如下所示:

$('.btn-danger').click(function() {
  var timer;
  var $alerts = $('#alerts');
  var count = $alerts.data('count');
  var $alert = $(
    '<div class="alert alert-danger" role="alert" data-dismiss="alert">' +
      count +
    '</div>'
  );
  $alerts.append($alert);
  startTimer();
  $alert.on( 'mousemove', startTimer );
  count += 1;
  $alerts.data('count', count);

  function startTimer() {
    clearTimeout( timer );
    timer = setTimeout( function() {
      $alert.hide();
    }, 3000 );
  }
});

这是this version of the fiddle .

我现在的最后一个建议...除非您确实需要将 count 值存储在 data-count DOM 属性中,否则我建议只使用 JavaScript 变量为此:

(function() {
  var count = 0;
  $('.btn-danger').click(function() {
    ++count;
    var timer;
    var $alerts = $('#alerts');
    var $alert = $(
      '<div class="alert alert-danger" role="alert" data-dismiss="alert">' +
        count +
      '</div>'
    );
    $alerts.append($alert);
    startTimer();
    $alert.on( 'mousemove', startTimer );

    function startTimer() {
      clearTimeout( timer );
      timer = setTimeout( function() {
        $alert.hide();
      }, 3000 );
    }
  });
})();

这是我的 final fiddle for the night ,以及可运行的代码片段:

(function() {
  var count = 0;
  $('.btn-danger').click(function() {
    count += 1;
    var timer;
    var $alerts = $('#alerts');
    var $alert = $(
      '<div class="alert alert-danger" role="alert" data-dismiss="alert">' +
        count +
      '</div>'
    );
    $alerts.append($alert);
    startTimer();
    $alert.on( 'mousemove', startTimer );

    function startTimer() {
      clearTimeout( timer );
      timer = setTimeout( function() {
        $alert.hide();
      }, 3000 );
    }
  });
})();
#site {
  height: 100%;
  width: 100%;
  position: absolute;
  top:0;
  left:0;
  background-color: cyan;
}
#alerts {
  position: absolute;
  right:0;
  bottom:0;
  width: 200px;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<div id="site">
  <div class="btn btn-danger">Red Alert!</div>
  <div id="alerts" data-count="1">
  </div>
</div>

接下来,我将向您提出一个挑战。如果您尝试一下,您可能会注意到一些不理想的情况。一是你必须保持鼠标移动以防止超时。您可以使用 mouseentermouseleave,而不是像我在这段代码中那样使用 mousemove。与此相关的是,如果鼠标悬停在任何警报上,停止所有超时似乎可能会更好。否则,当清除另一个警报时,鼠标悬停的警报可能会从其下方滑出。这应该也不难做到。

黑客快乐!

关于因潜在扩展而过期的 Javascript 警报,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41604536/

相关文章:

javascript - 如何将命名函数与 for each 和 this 一起使用

javascript - JS重定向不加载静态内容

javascript - 使用 AJAX 的 JQuery 自动完成

javascript - 清除 Bootstrap 可编辑表单

javascript - 使用 % 宽度时的 JScrollPane 问题

javascript - 启用和禁用 HTML 按钮单击下拉菜单

javascript - 打印object标签的url加载的页面

javascript - 格式化javascript日期以匹配rails格式

javascript - 具有多个图像的 map 区域的鼠标悬停过渡

javascript - 当通过 Javascript 按下回车按钮时调用一个函数