jQuery 在 .each() 循环中使用 .delay() 方法



使用以下代码,我希望li元素一个接一个地淡入,但所有元素一起淡入:

$('li').each(function () {
    $(this).delay(1000).fadeIn(1000);
});

谁能解释为什么它们不会一个接一个地消失?

.delay 调用不会阻止循环立即进行,因此所有延迟和动画将(几乎)立即开始。

最简单的解决方案是按当前索引号错开延迟:

$('li').each(function(index) {
    $(this).delay(1000 * index).fadeIn(1000);
});

更好的解决方案是使用伪递归循环和动画的"完成回调"来触发下一次迭代:

var els = $('li').get();
(function loop() {
    if (els.length) {
        var el = els.shift();
        $(el).fadeIn(1000, loop);
    }
})();

此方法通常更可取,因为它确保在前一个动画完成之前不可能开始下一个淡入,并且还避免创建多个并行延迟/淡入队列(每个元素一个),因为第二个动画在第一个动画完成之前不会排队。

我想

这是因为您基本上告诉每个li等待 1 秒并淡入。所以这就是他们所做的:)

现在,您的代码类似于:

$('li').delay(1000).fadeIn(1000);

尝试这样的事情:

var delay = 0;
$('li').each(function () {
    $(this).delay(delay).fadeIn(1000);
    delay += 1000;
});

或者,正如Alnitak所建议的那样,一个更干净的方法是使用$.each()提供的当前索引

$('li').each(function (index) {
    // index will return the loop index starting to 0
    $(this).delay(index*1000).fadeIn(1000);
});

因为each没有延迟。几乎同时应用每个延迟。

您可能想尝试使用complete部分 do fadeIn下一个元素

.fadeIn( [duration ] [, complete ] )

jQuery api doc

这是

jQuery.each的误解。这并不意味着要做一个,然后等待它完成然后再继续,为此你需要使用承诺。

相反,请尝试将延迟更改为数组中每个 LI 索引的倍数,例如:

$('li').each(function(index) {
  $(this).delay((index + 1) * 1000).fadeIn(1000);
});

由于数组索引总是从 0 开始,并且 0 * 1000 = 0,因此我在乘以 1000 之前将 1 添加到索引中,以确保第一个在 1 秒后发生,第二个在 2 秒后发生,依此类推。

如果您不希望第一个li淡入 1s 的延迟,那么它很简单:

$('li').each(function(index) {
  $(this).delay(index * 1000).fadeIn(1000);
});