$(".content")
.load("content/intro.html #bt")
.hide()
.fadeIn(2000)
.delay(2000)
.fadeOut(2000)
.load("content/intro.html #ofm")
.fadeIn(2000)
.fadeOut(2000)
.load("content/main.html")
.fadeIn(800);
我希望jQuery首先加载内容(intro.html #bt
等)但它实际上会加载main.html
而不会执行列表中的其他内容。在这种情况下,三次淡出。什么是变通方法?
答案 0 :(得分:4)
这可能是违反直觉的,但在理解jQuery的工作方式时会很有意义。
您呼叫的所有方法都是在同一时间开始的。所以它加载所有三个html页面,但你的眼睛只看到最后一个,然后你看到动画启动。你需要告诉jQuery等待每个命令完成后再执行下一个。
(你正在做什么被称为 chaining ,虽然它是quite useful,但它并不像你想要的那样工作,而且这不是你需要的。)
通过使用回调或deferred pattern,执行流程可以是控制器。 jQuery实现了两者(我认为仅在v1.5之后延迟)但load()
只实现了回调。
基本上,你告诉jQuery要加载东西并运行动画,但你不告诉它等待上一个命令完成后再继续。
这是达到你想要的一种方式。我没有测试它,但它证明了原理。
$(".content")
.load("content/intro.html #bt", function() {
$(this).hide().fadeIn(2000, function() {
$(this).fadeOut(2000, function(){
$(this).load("content/intro.html #ofm", function() {
$(this).fadeIn(2000, function() {
$(this).fadeOut(2000, function() {
$(this).load("content/main.html", function(){
$(this).fadeIn(800);
});
});
});
});
});
});
});
注意每个方法如何回调?这样,您就知道在继续之前已完成上一个方法的执行。
注意,这段代码远非理想!有更好的方法可以使用deferred模式和the many jQuery pulse plugins之一来实现此模式。
一旦你理解了为什么jQuery以这种方式工作,请查看Paul irish's post on how to address the ugly syntax this creates。
您可能还需要签出TameJS,它会在javascript中添加一个名为await
的构造,以简化此类代码。
答案 1 :(得分:0)
加上我的两分钱:
可以用帮助器链接这些东西(在某种程度上)。我一直希望能够将动画和负载链接在一起,所以在阅读了你的问题之后,最后决定深入挖掘并最终弄清楚如何将这些东西链接起来,这就是我想出来的。
function Resolver () {
this.itemsToResolve = [];
this.context = {};
//this.context is only needed if you want to pass
//something to the next anonymous function
this.next = function(){
var def = $.Deferred();
def.then.apply(def,arguments);
this.itemsToResolve.push(def);
return this;
};
this.resolveNext = $.proxy(function(){
var p = this.itemsToResolve.shift();
if (p){
p.resolve(this);
}
}, this);
};
严格地说,我可能甚至不需要使用jQuery的延迟(s),但我正在努力研究可以充分利用它们的东西 - 如果这有任何意义,我不确定这对我有意义!
使用该帮助程序,这里修改了您的代码以使用它:
var $c = $(".content");
var res = new Resolver();
res.next(function(r){
$c.load("content/intro.html #bt",r.resolveNext);
}).next(function(r){
$c.hide()
.fadeIn(2000)
.delay(2000)
.fadeOut(2000,r.resolveNext);
}).next(function(r){
$c.load("content/intro.html #ofm",r.resolveNext);
}).next(function(r){
$c.fadeIn(2000)
.fadeOut(2000, r.resolveNext);
}).next(function(r){
$c.load("content/main.html",r.resolveNext);
}).next(function(r){
$c.fadeIn(800, r.resolveNext);
});
//and then finally, to start it off
res.resolveNext();
可能有更精致的方法来做到这一点,但除此之外,我对它很满意。