我在html里有很多div。每个div包含动画或一些js代码,这些代码仅在该div可见时调用:
<button id='start' class='start'>Start</button>
<div class="step1 later">
<div class='red later'>Show first</div>
<div class='aqua later'>Show later</div>
</div>
<div class="step2 later">
<div class='green later'>Show together</div>
<div class='yellow later'>Show together</div>
</div>我的目标是用div类显示step1,调用一些js,然后显示step2等等。看上去像滑块。在这个例子中,我想要显示step1,然后用red类显示div,延迟之后我想显示aqua。接下来,我们将进入step2并立即显示两个div:yellow、green。我已经决定使用承诺(Q.js)来实现这一目标。这是我的密码:
$(function () {
var currentStep = 1,
handlers = {};
$('#start').click(function() {
for(var i = 0; i < 2; i++) {
showStep(currentStep + i);
}
});
function showStep(step) {
var name = 'step' + step;
$('.' + name).show();
handlers[name]();
}
handlers.step1 = function() {
Q().then(function() {
$('.notification').html('Step1 started');
})
.delay(2000)
.then(function() {
showElem('red');
})
.delay(2000)
.then(function() {
showElem('aqua');
});
};
handlers.step2 = function() {
Q().then(function() {
$('.notification').append('Step2 started');
})
.delay(2000)
.then(function() {
showElem('green');
showElem('yellow');
});
};
function showElem(classSelector) {
$('.' + classSelector).fadeIn(100);
}
});除了一件事外,所有的动画和延迟作品都能找到。当一个步骤完成时,我的代码不会等待,处理程序几乎同时启动。
演示:JSBIN
发布于 2015-06-05 23:58:14
使用q来调度jQuery操作是非常不常规的。通过明智地使用它的.delay()和.promise()方法,jQuery能够很好地独立完成这项工作。
在以下代码重写中:
.then()链。showElem()和showStep()是不必要的并且消失了handlers是作为一个对象文字编写的。jQuery(function ($) {
var handlers = {
'step1': function() {
$('.notification').html('<div>Step1 started</div>');
return $(".step1").show(0).delay(2000).promise().then(function() {
return $('.red').fadeIn(100).delay(2000).promise();
}).then(function() {
return $('.aqua').fadeIn(100).promise();
});
},
'step2': function() {
$('.notification').append('<div>Step2 started</div>');
return $(".step2").show(0).delay(2000).promise().then(function() {
return $('.green, .yellow').fadeIn(100);
});
}
};
$('#start').click(function() {
handlers.step1().then(handlers.step2);
});
});演示
编辑
对于大量的处理程序,您可以按照以下方式长出"start“例程:
$('#start').click(function() {
handlers.step1()
.then(handlers.step2)
.then(handlers.step3)
.then(handlers.step4)
.then(handlers.step5)
.then(handlers.step6)
...
;
});但是,这可能需要大量输入,并且不能满足不同数量的处理程序的需要。
解决方案相当简单。
首先,将handlers写为数组,而不是对象。
var handlers = [
//step 0
function() {
$('.notification').html('<div>Step1 started</div>');
return $(".step1").show(0).delay(2000).promise().then(function() {
return $('.red').fadeIn(100).delay(2000).promise();
}).then(function() {
return $('.aqua').fadeIn(100).promise();
});
},
//step 1
function() {
$('.notification').append('<div>Step2 started</div>');
return $(".step2").show(0).delay(2000).promise().then(function() {
return $('.green, .yellow').fadeIn(100);
});
},
//step 2,
...
//step 3,
...
];现在,您可以使用array方法.reduce()扫描数组,构建承诺链:
$('#start').click(function() {
handlers.reduce(function(promise, handler) {
return promise.then(handler);
}, $.when());
});在这里,$.when()是一个解决的“种子”承诺,使链启动。
演示
发布于 2015-06-05 17:13:05
问题在于您的初始" for“循环,在该循环中,您在一次执行中执行了所有"showStep”,而无需等待承诺。
相反,你可以这样做:
$('#start').click(function() {
showStep(1);
});
function showStep(step) {
var name = 'step' + step;
$('.' + name).show();
handlers[name]().then(function() {
if (step < 2) {
showStep(step+1);
}
});
}让你的操纵者还承诺。
https://stackoverflow.com/questions/30671630
复制相似问题