我出现了 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);
});
最佳答案
所有警报立即消失并且您无法添加新警报的原因是以下代码:
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>
接下来,我将向您提出一个挑战。如果您尝试一下,您可能会注意到一些不理想的情况。一是你必须保持鼠标移动以防止超时。您可以使用 mouseenter
和 mouseleave
,而不是像我在这段代码中那样使用 mousemove
。与此相关的是,如果鼠标悬停在任何警报上,停止所有超时似乎可能会更好。否则,当清除另一个警报时,鼠标悬停的警报可能会从其下方滑出。这应该也不难做到。
黑客快乐!
关于因潜在扩展而过期的 Javascript 警报,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41604536/