8.queue,队列管理

本文详细解析jQuery的队列管理,包括`jQuery.extend`和`jQuery.fn.extend`中的`queue`、`dequeue`、`delay`、`clearQueue`和`promise`等方法的实现原理和使用场景,阐述如何在数据对象中添加属性并创建和操作队列。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简介:

在data的基础上,在数据对象中添加一个一个属性,属性内容指定是数组队列。

代码大体框架:

jQuery.extend({
	queue: function( elem, type, data ) {
	},
	dequeue: function( elem, type ) {
	},
	_queueHooks: function( elem, type ) {
	}
});

jQuery.fn.extend({
	queue: function( type, data ) {
	},
	dequeue: function( type ) {
	},
	delay: function( time, type ) {
	},
	clearQueue: function( type ) {
	},
	promise: function( type, obj ) {
	}
});

代码解析:

jQuery.extend:

使用$调用的jQuery队列相关方法。

  • queue:

queue: function( elem, type, data ) {
	var queue;
	if ( elem ) {
		type = ( type || "fx" ) + "queue";
		queue = data_priv.get( elem, type );
		if ( data ) {
			if ( !queue || jQuery.isArray( data ) ) {
				queue = data_priv.access( elem, type, jQuery.makeArray(data) );
			} else {
				queue.push( data );
			}
		}
		return queue || [];
	}
},

输入三个参数,挂载数据的元素elem;属性名type;数据data。

判断元素是否存在,只有存在的基础上,才能有挂载。存在的话进行队列的创建和数据的添加。

为type赋值,type = ( type || "fx" ) + "queue",以对应队列在数据对象中的属性名。(不存在的话,就是默认fxqueue)

在data_priv实例对象中,取出对应的队列数据。在判断data是否存在,不存在的话,直接返回队列数据,存在的话,再次判断,如果队列不存在,就是用data_priv.access创建一个,将数据添加进行,如果队列存在,但是data是数组,就让data的数据覆盖原来的队列,如果队列存在,data不是数组,就使用push将元素添加到队列中,

  • _queueHooks:

_queueHooks: function( elem, type ) {
	var key = type + "queueHooks";
	return data_priv.get( elem, key ) || data_priv.access( elem, key, {
		empty: jQuery.Callbacks("once memory").add(function() {
			data_priv.remove( elem, [ type + "queue", key ] );
		})
	});
}

传入两个参数,挂载数据的元素elem;属性名type;

创建属性名key,为key = type + "queueHooks"。

返回结果,先使用data_priv.get,获取挂载在元素上的数据对象中,属性名为key的属性内容;如果不存在的话,就使用data_priv.access,为挂载在元素上的数据对象添加属性key内容是一个对象对象内存在属性empty,内容是一个标识为once memory的回调函数,为这个对调函数添加一个函数,data_priv.remove( elem, [ type + "queue", key ] );,即使用data_priv.remove移除挂载在元素上的数据对象中的属性type + "queue", key。

  • dequeue:

dequeue: function( elem, type ) {
	type = type || "fx";
	var queue = jQuery.queue( elem, type ),
		startLength = queue.length,
		fn = queue.shift(),
		hooks = jQuery._queueHooks( elem, type ),
		next = function() {
			jQuery.dequeue( elem, type );
		};
	if ( fn === "inprogress" ) {
		fn = queue.shift();
		startLength--;
	}
	if ( fn ) {
		if ( type === "fx" ) {
			queue.unshift( "inprogress" );
		}
		delete hooks.stop;
		fn.call( elem, next, hooks );
	}
	if ( !startLength && hooks ) {
		hooks.empty.fire();
	}
},

输入两个个参数,挂载数据的元素elem;属性名type;(应该通常用于内部)

对type进行重新赋值,type如果存在就是type,不存在的话,就是默认值"fx"。

之后创建相关变量:

  • queue:通过jQuery.queue,创建或者获取挂载在元素上的队列
  • startLength:队列长度
  • fn:数组的shift()执行结果,作用是移除数组中的第一个项并返回该项,同时将数组长度减1。(也就是说,以及移除第一项了)
  • hooks:_queueHooks返回的一个callback函数的self结果。
  • next:函数,内部执行jQuery.dequeue( elem, type )

如果第一个被移除的元素是字符串"inprogress"的话,就再次执行queue.shift(),startLength减一。

如果fn存在的话,如果type等于默认的字符串"fx",就将"inprogress"字符串压入队列首项。

之后删除hooks的stop属性,然后使用call执行,将elem作为this指向,传入参数next, hooks(使用dequeue移除元素的话, 必须是函数,不然会报错。所以一般使用队列处理函数。)

最后,如果startLength为0且hooks存在的话,执行hooks.empty.fire();,删除挂载在元素上的数据对象中的队列数组。

jQuery.fn.extend:

使用$()调用的jQuery队列相关方法。

  • queue:

queue: function( type, data ) {
	var setter = 2;
	if ( typeof type !== "string" ) {
		data = type;
		type = "fx";
		setter--;
	}
	if ( arguments.length < setter ) {
		return jQuery.queue( this[0], type );
	}
	return data === undefined ?
		this :
		this.each(function() {
			var queue = jQuery.queue( this, type, data );
			jQuery._queueHooks( this, type );
			if ( type === "fx" && queue[0] !== "inprogress" ) {
				jQuery.dequeue( this, type );
			}
		});
},

传入两个参数,type代表属性;data代表数据。

创建变量setter,初始化为2,用来判定传入的参数类型。

如果type的类型不是字符串的话(为对象),将type赋值给data,然后type赋值为默认的"fx",setter减一。

如果传入的参数数量少于setter的话,(只传入一个字符串)直接返回对应字符串的队列数据。

返回结果,

  1. 如果data等于undefined的话(type是字符串,但是data传入了undefined)返回jQuery实例对象;
  2. 如果data不等于undefined的话,实例jQuery执行each函数,为每个实例中的节点元素挂载数据对象,再为对象添加队列数组属性。调用执行jQuery._queueHooks。如果type等于默认的'fx'且队列的第一个元素不为"inprogress",(应该是针对内部的动画,复用性太强,导致解读就比较费劲)执行jQuery.dequeue( this, type ),移除数据。
  • dequeue

dequeue: function( type ) {
	return this.each(function() {
		jQuery.dequeue( this, type );
	});
},

传入type,遍历jQuery实例,每个元素使用jQuery.dequeue移除数据。

  • delay:

delay: function( time, type ) {
	time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
	type = type || "fx";
	return this.queue( type, function( next, hooks ) {
		var timeout = setTimeout( next, time );
		hooks.stop = function() {
			clearTimeout( timeout );
		};
	});
},

用于延迟函数的执行,传入time表示延迟时间和type属性名。

返回,在队列中传入一个函数,函数传入next执行函数,hooks回调对象。

创建一个定时器,传入执行函数next,时间time。

为hooks添加一个属性stop,用于清除定时器。

  • clearQueue:

clearQueue: function( type ) {
	return this.queue( type || "fx", [] );
},

清空移除队列中的所有数据,转为空数组。

  • promise:

promise: function( type, obj ) {
	var tmp,
		count = 1,
		defer = jQuery.Deferred(),
		elements = this,
		i = this.length,
		resolve = function() {
			if ( !( --count ) ) {
				defer.resolveWith( elements, [ elements ] );
			}
		};
	if ( typeof type !== "string" ) {
		obj = type;
		type = undefined;
	}
	type = type || "fx";
	while( i-- ) {
		tmp = data_priv.get( elements[ i ], type + "queueHooks" );
		if ( tmp && tmp.empty ) {
			count++;
			tmp.empty.add( resolve );
		}
	}
	resolve();
	return defer.promise( obj );
}

等队列中的所有函数都执行完毕了,在执行传入的函数。

创建变量,tmp,表示队列数组;count,表示队列中需要执行的函数数量;defer,jQuery.Defferred()对象;elements挂载的元素数组(jQuery实例对象);i,表示元素长度;resolve,执行存储在defer内的函数,只有count大于1,就会执行defer中的函数。

如果type的类型不是字符串的话,将type赋值给obj,type赋值为undefined。

对type再赋值,如果存在就不变,不存在的话,就是"fx"默认值。

while循环 i 次,每次,将data_priv对应type + "queueHooks"的队列数组赋值给tmp。

如果tmp且tmp.empty存在就count++,并且添加resolve(由于是"once memory"标识)

调用resolve(),执行函数。

返回defer.promise( obj )。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值