内容简介:前言:需要先看
前言:
需要先看 jQuery源码解析之 $ .queue()、 $ .dequeue()和jQuery.Callbacks()
一、举例
divA 的宽度先变成 500px,再变成 300px,最后变成 1000px:
<script src="jQuery.js"></script>
<div id="A" style="width:100px;height:50px;background-color: deeppink">这是A</div>
<script>
let A = document.querySelector('#A');
//在异步调用中,进行同步调用
//动画是异步的
A.onclick = function() {
//就是连续调用animation.add()
$('#A').animate({
'width': '500'
}).animate({
'width': '300'
}).animate({
'width': '1000'
});
};
</script>
二、 $ ().animate()
作用:
通过 CSS 样式将元素从一个状态改变为另一个状态
源码:
//之前有说过: jQuery.fn.extend() 是$()的方法
jQuery.fn.extend( {
//源码8062行
//{'width': '500'}
animate: function( prop, speed, easing, callback ) {
//是否是空对象,false
var empty = jQuery.isEmptyObject( prop ),
// optall={
// complete:function(){jQuery.dequeue()},
// old:false,
// duration: 400,
// easing: undefined,
// queue:"fx",
// }
//undefined undefined undefined
optall = jQuery.speed( speed, easing, callback ),
doAnimation = function() {
// Operate on a copy of prop so per-property easing won't be lost
//Animation 方法执行单个动画的封装
//doAnimation的本质是执行Animation方法
//this:目标元素
//{'width': '500'}
//optall={xxx}
var anim = Animation( this, jQuery.extend( {}, prop ), optall );
// Empty animations, or finishing resolves immediately
//finish是数据缓存的一个全局变量
//如果为true,立即终止动画
if ( empty || dataPriv.get( this, "finish" ) ) {
anim.stop( true );
}
};
//注意这个
//自身的.finish=自身
doAnimation.finish = doAnimation;
return empty || optall.queue === false ?
this.each( doAnimation ) :
//一般走这里
//通过 queue 调度动画之间的衔接
//optall.queue:"fx"
//doAnimation:function(){}
this.queue( optall.queue, doAnimation );
},
})
解析:
(1)jQuery.speed()
作用:
初始化动画对象的属性
源码:
//源码8009行
//undefiend undefined undefined
//作用是返回一个经过修改的opt对象
jQuery.speed = function( speed, easing, fn ) {
// opt={
// complete:false,
// duration: undefined,
// easing: undefined,
// }
var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
complete: fn || !fn && easing ||
isFunction( speed ) && speed,
duration: speed,
easing: fn && easing || easing && !isFunction( easing ) && easing
};
// Go to the end state if fx are off
/*这边是为opt.duration赋值的*/
//undefiend
if ( jQuery.fx.off ) {
opt.duration = 0;
} else {
if ( typeof opt.duration !== "number" ) {
if ( opt.duration in jQuery.fx.speeds ) {
opt.duration = jQuery.fx.speeds[ opt.duration ];
} else {
//走这边
//_default=400
opt.duration = jQuery.fx.speeds._default;
}
}
}
/*为opt.queue赋值*/
// Normalize opt.queue - true/undefined/null -> "fx"
//注意这个==,是模糊判断
if ( opt.queue == null || opt.queue === true ) {
opt.queue = "fx";
}
// Queueing
/*为opt.old赋值*/
opt.old = opt.complete;
opt.complete = function() {
if ( isFunction( opt.old ) ) {
opt.old.call( this );
}
//如果queue有值得话,就出队列
//因为queue默认为"fx",所以一般会触发dequeue操作
if ( opt.queue ) {
//this指目标元素
//opt.queue
jQuery.dequeue( this, opt.queue );
}
};
//此时的opt为:
// opt={
// complete:function(){jQuery.dequeue()},
// old:false,
// duration: 400,
// easing: undefined,
// queue:"fx",
// }
return opt;
};
解析:
通过传入的三个参数,对 opt 对象进行处理,如果三个参数都为 undefined 的话, opt 等于:
opt={
complete:function(){jQuery.dequeue()},
old:false,
duration: 400,
easing: undefined,
queue:"fx",
}
(2) animate 内部做了什么?
作用:
animate 内部封装了一个 doAnimation 触发器,触发器触发就会运行 Animation 方法, animate 最后返回的是 queue() 方法,注意 queue() 方法的参数带有触发器 doAnimation
(3) $().queue()
作用:
执行入队操作( jQuery.queue() ),如果是fx动画的话,同时执行出队操作( jQuery.dequeue() )
源码
这个方法上篇文章已经分析过了,这里就简单分析下:
jQuery.fn.extend( {
//optall.queue:"fx"
//doAnimation:function(){}
//fx动画的话,就执行dequeue(),也就是队首callback函数
queue: function( type, data ) {
//返回的是数组[doAnimate,doAnimate,xxx]
var queue = jQuery.queue( this, type, data );
//初始化hooks
jQuery._queueHooks( this, type );
/*专门为fx动画做处理*/
//如果队首没有锁的话,直接运行队首元素
if ( type === "fx" && queue[ 0 ] !== "inprogress" ) {
jQuery.dequeue( this, type );
}
},
解析:
inprogress 是动画队列的锁,目的是 保证上个动画执行结束后,再去执行下个动画
每入队一个 doAnimate 函数,如果队首没有 inprogress 锁的话,就会出队去运行一个 doAnimate 函数
jQuery._queueHooks() 的意义在于添加一个 empty.remove() 方法,用来清空队列 queue
(4) jQuery.queue()
作用:
上篇文章也分析过了,就是将 doAnimate 函数 push 进 queue 数组中
(5) jQuery.dequeue()
作用:
如果队首元素不是 inprogress ,而是 doAnimation 方法,则先将 doAnimation 出队,再让 inprogress 入队首,再运行 doAnimation 方法;
如果队首元素是 inprogress 的话,则移除锁
如果队列为空的话,则清空 queue ,节省内存
源码:
//源码4624行
//目标元素,'type'
dequeue: function( elem, type ) {
//'type'
type = type || "fx";
//get,获取目标元素的队列
var queue = jQuery.queue( elem, type ),
//长度
startLength = queue.length,
//去除对首元素,并返回该元素
fn = queue.shift(),
//确保该队列有一个hooks
hooks = jQuery._queueHooks( elem, type ),
//next相当于dequeue的触发器
next = function() {
jQuery.dequeue( elem, type );
};
// If the fx queue is dequeued, always remove the progress sentinel
//如果fn='inprogress',说明是fx动画队列正在出队,就移除inprogress
if ( fn === "inprogress" ) {
fn = queue.shift();
startLength--;
}
if ( fn ) {
// Add a progress sentinel to prevent the fx queue from being
// automatically dequeued
//如果是fx动画队列的话,就添加inprogress标志,来防止自动出队执行
//意思应该是等上一个动画执行完毕后,再执行下一个动画
if ( type === "fx" ) {
queue.unshift( "inprogress" );
}
// Clear up the last queue stop function
//删除hooks的stop属性方法
delete hooks.stop;
//递归dequeue方法
fn.call( elem, next, hooks );
}
console.log(startLength,'startLength4669')
//如果队列是一个空数组,并且hooks存在的话,清除该队列
if ( !startLength && hooks ) {
//进行队列清理
hooks.empty.fire();
console.log(hooks.empty.fire(),'bbbb4671')
}
},
解析:
循环同步运行多个 doAnimation() 方法,直到队列为空
综上,除 doAnimation 内的逻辑外, 整个 $().animate() 的流程图 为:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- ReactNative源码解析-初识源码
- Spring源码系列:BeanDefinition源码解析
- Spring源码分析:AOP源码解析(下篇)
- Spring源码分析:AOP源码解析(上篇)
- 注册中心 Eureka 源码解析 —— EndPoint 与 解析器
- 新一代Json解析库Moshi源码解析
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Mastering Regular Expressions, Second Edition
Jeffrey E F Friedl / O'Reilly Media / 2002-07-15 / USD 39.95
Regular expressions are an extremely powerful tool for manipulating text and data. They have spread like wildfire in recent years, now offered as standard features in Perl, Java, VB.NET and C# (and an......一起来看看 《Mastering Regular Expressions, Second Edition》 这本书的介绍吧!