Deferred物件移植到animate源码备忘笔记
[2011-10-04 21:10:03 --@jQuery]
动画结束从表象上看有2种形式:
常规形式:
opt.complete是动画(队列中的某一个,或独立动画[queue===false])结束时必然执行的函数。
stop形式:
gotoEnd参数布尔值:
true时:即动画结束时到达目标属性值,这种方式等同于常规形式,执行opt.complete函数。
false时:动画结束时不到达目标属性值,执行jQuery._unmark函数以及dequeue()函数;
即依据动画结束是否时到达目标属性值来分为2类:
执行opt.complete函数
执行jQuery._unmark函数以及dequeue()函数
opt.complete函数源码:
opt.complete = function(noUnmark) { ...
if (opt.queue !== false) {//队列中的动画,会执行jQuery物件的dequeue函数
jQuery.dequeue(this);//执行jQuery.dequeue函数
} else if (noUnmark !== false) {//独立动画时则执行
jQuery._unmark(this);
}
};
即归结到这两个函数:
jQuery._unmark
jQuery.dequeue
jQuery._unmark对应的函数为jQuery._mark。
jQuery._mark函数给dom节点data数据里默认以'fxmark'为key值累加1存储一个数值为相应value。
jQuery._mark函数在jQuery源码中只用到一句:在非队列动画时执行:
jQuery._unmark用到2句。见以上源码中分析中。即:
在每个独立动画执行结束时执行 data_fxmark -=1,在最后一个动画执行结束时执行 data_fxmark =0
在stop函数!gotoEnd时,data_fxmark =0
jQuery._unmark,在data_fxmark =0时:
dequeue函数:
即在动画全部结束时,队列为空或独立动画已全部结束时,都执行了handleQueueMarkDefer:
Deferred物件移植到animate的函数是jQuery对象的promise方法,默认功能为监测一组jQuery对象所有dom节点动画结束最后时间点:
promise函数内部会为每个dom节点存储一个jQuery._Deferred()物件,此物件会在handleQueueMarkDefer进行resolve,相应地执行一个内部名为resolve的函数,该函数内部有个计数器,去判断是否是所有dom中最后一个结束动画的dom节点。从而把Deferred物件移植到了animate中。非常赞叹的功能。
常规形式:
opt.complete是动画(队列中的某一个,或独立动画[queue===false])结束时必然执行的函数。
stop形式:
gotoEnd参数布尔值:
true时:即动画结束时到达目标属性值,这种方式等同于常规形式,执行opt.complete函数。
false时:动画结束时不到达目标属性值,执行jQuery._unmark函数以及dequeue()函数;
stop: function(clearQueue, gotoEnd) {
...
// clear marker counters if we know they won't be
if (!gotoEnd) {
jQuery._unmark(true, this);
}
// start the next in the queue if the last step wasn't forced
if (!gotoEnd) {
this.dequeue();
}
...
}
...
// clear marker counters if we know they won't be
if (!gotoEnd) {
jQuery._unmark(true, this);
}
// start the next in the queue if the last step wasn't forced
if (!gotoEnd) {
this.dequeue();
}
...
}
即依据动画结束是否时到达目标属性值来分为2类:
执行opt.complete函数
执行jQuery._unmark函数以及dequeue()函数
opt.complete函数源码:
opt.complete = function(noUnmark) { ...
if (opt.queue !== false) {//队列中的动画,会执行jQuery物件的dequeue函数
jQuery.dequeue(this);//执行jQuery.dequeue函数
} else if (noUnmark !== false) {//独立动画时则执行
jQuery._unmark(this);
}
};
即归结到这两个函数:
jQuery._unmark
jQuery.dequeue
jQuery._unmark对应的函数为jQuery._mark。
jQuery._mark函数给dom节点data数据里默认以'fxmark'为key值累加1存储一个数值为相应value。
jQuery._mark函数在jQuery源码中只用到一句:在非队列动画时执行:
if (optall.queue === false) {
jQuery._mark(this)
}
jQuery._mark(this)
}
jQuery._unmark用到2句。见以上源码中分析中。即:
在每个独立动画执行结束时执行 data_fxmark -=1,在最后一个动画执行结束时执行 data_fxmark =0
在stop函数!gotoEnd时,data_fxmark =0
jQuery._unmark,在data_fxmark =0时:
jQuery.removeData(elem, key, true);
handleQueueMarkDefer(elem, type, "mark");
handleQueueMarkDefer(elem, type, "mark");
dequeue函数:
...
if (!queue.length) {//在队列为空时
jQuery.removeData(elem, type + "queue", true);
handleQueueMarkDefer(elem, type, "queue");
}
...
if (!queue.length) {//在队列为空时
jQuery.removeData(elem, type + "queue", true);
handleQueueMarkDefer(elem, type, "queue");
}
...
即在动画全部结束时,队列为空或独立动画已全部结束时,都执行了handleQueueMarkDefer:
function handleQueueMarkDefer(elem, type, src) {
...
defer = jQuery.data(elem, deferDataKey, undefined, true);//defer是在执行jQuery对象promise方法是存进data里的。
if (defer) {
// Give room for hard-coded callbacks to fire first
// and eventually mark/queue something else on the element
setTimeout(function() {
if (!jQuery.data(elem, queueDataKey, undefined, true) && !jQuery.data(elem, markDataKey, undefined, true))
{//在不存在data_fxqueue以及data_fxmark时,这里我的疑问是,如果执行到handleQueueMarkDefer函数,这个条件必然成立,为什么这里还要加上判断,而且这个src参数属于多余。
jQuery.removeData(elem, deferDataKey, true);
defer.resolve();//resolve该怎么翻译好?
}
},
0);
}
}
...
defer = jQuery.data(elem, deferDataKey, undefined, true);//defer是在执行jQuery对象promise方法是存进data里的。
if (defer) {
// Give room for hard-coded callbacks to fire first
// and eventually mark/queue something else on the element
setTimeout(function() {
if (!jQuery.data(elem, queueDataKey, undefined, true) && !jQuery.data(elem, markDataKey, undefined, true))
{//在不存在data_fxqueue以及data_fxmark时,这里我的疑问是,如果执行到handleQueueMarkDefer函数,这个条件必然成立,为什么这里还要加上判断,而且这个src参数属于多余。
jQuery.removeData(elem, deferDataKey, true);
defer.resolve();//resolve该怎么翻译好?
}
},
0);
}
}
Deferred物件移植到animate的函数是jQuery对象的promise方法,默认功能为监测一组jQuery对象所有dom节点动画结束最后时间点:
a.animate({
width: 450
},
{
duration: 3000,
complete: function() {
alert('complete')
}
}).animate({
height: 300
},
{
duration: 5000,
queue: false
});
var t = $('.a').promise();
t.done(function() {
alert(5)
});
...
$.when($('a'),$('b'),...).done(...);
...
width: 450
},
{
duration: 3000,
complete: function() {
alert('complete')
}
}).animate({
height: 300
},
{
duration: 5000,
queue: false
});
var t = $('.a').promise();
t.done(function() {
alert(5)
});
...
$.when($('a'),$('b'),...).done(...);
...
promise函数内部会为每个dom节点存储一个jQuery._Deferred()物件,此物件会在handleQueueMarkDefer进行resolve,相应地执行一个内部名为resolve的函数,该函数内部有个计数器,去判断是否是所有dom中最后一个结束动画的dom节点。从而把Deferred物件移植到了animate中。非常赞叹的功能。
本文禁止复制/转载!
共 1 评论
1. 2011-11-01 22:11:27,from Danyon