Skip to main content
 首页 » 编程设计

jQuery之queue队列源码分析(非动画部分)

2022年07月16日156落叶
  1 jQuery.extend({ 
  2         // 显示或操作在匹配元素上执行的函数队列 
  3         queue: function (elem, type, data) { 
  4             var queue; 
  5  
  6             if (elem) { 
  7                 // type没定义的话就默认使用fxqueue 
  8                 type = (type || 'fx') + 'queue'; 
  9                 // 先获取elem上的缓存数据 
 10                 queue = jQuery._data(elem, type); 
 11  
 12                 if (data) { 
 13                     // 如果没有缓存数据或者data是数组 
 14                     // 则给elem设置缓存数据 
 15                     if (!queue || jQuery.isArray(data)) { 
 16                         queue = jQuery._data(elem, type, jQuery.makeArray(data)); 
 17                     } else { 
 18                         // 否则存在缓存数据数组直接入栈 
 19                         queue.push(data); 
 20                     } 
 21                 } 
 22                 return queue || []; 
 23             } 
 24         }, 
 25         // 从队列最前端移除一个队列函数,并执行它 
 26         dequeue: function (elem, type) { 
 27             type = type || 'fx'; 
 28  
 29             var 
 30             // 获取缓存队列 
 31                 queue = jQuery.queue(elem, type), 
 32                 startLength = queue.length, 
 33             // 取得队列的第一个元素 
 34                 fn = queue.shift(), 
 35             // 钩子对象,如果获取不到缓存的钩子对象,就设置新的钩子对象并返回 
 36                 hooks = jQuery._queueHooks(elem, type), 
 37             // 用来执行下一个队列 
 38                 next = function () { 
 39                     jQuery.dequeue(elem, type); 
 40                 }; 
 41  
 42             // 如果第一个元素是"inprogress",取下一个元素,长度相应减1 
 43             if (fn === 'inprogress') { 
 44                 fn = queue.shift(); 
 45                 startLength--; 
 46             } 
 47  
 48             // 为钩子对象添加cur方法 
 49             hooks.cur = fn; 
 50             // 如果此时fn不为null || false || undefined 
 51             if (fn) { 
 52                 // 如果type为“fx”,给队列添加"inprogress",防止自动出列(dequeue) 
 53                 if (type === 'fx') { 
 54                     queue.unshift('inprogress'); 
 55                 } 
 56  
 57                 // 删除上一个队列的stop函数 
 58                 delete hooks.stop; 
 59                 // 执行fn函数,并且把下一个队列函数设置为fn的第一个参数 
 60                 /* 
 61                 可以这样使用: 
 62                  $(document.body).queue('test', function(next){ 
 63                  console.log(11); 
 64                  next(); 
 65                  }); 
 66                  $(document.body).queue('test', function(){ 
 67                  console.log(22); 
 68                  }); 
 69                  $(document.body).dequeue('test'); 
 70                  */ 
 71                 fn.call(elem, next, hooks); 
 72             } 
 73  
 74             // 如果队列长度为0且存在钩子对象,则删除缓存 
 75             if (!startLength && hooks) { 
 76                 hooks.empty.fire(); 
 77             } 
 78         }, 
 79         // 私有方法,生成一个队列钩子对象(即从缓存数据中获取的队列钩子) 
 80         // 或者设置缓存队列钩子对象,这个对象的empty属性是一个Callbacks对象,这里的作用是删除缓存队列和缓存队列钩子的数据 
 81         _queueHooks: function (elem, type) { 
 82             var key = type + 'queueHooks'; 
 83             return jQuery._data(elem, key) || jQuery._data(elem, key, { 
 84                 empty: jQuery.Callbacks('once memory').add(function () { 
 85                     jQuery._removeData(elem, type + 'queue'); 
 86                     jQuery._removeData(elem, key); 
 87                 }) 
 88             }); 
 89         } 
 90     }); 
 91  
 92     jQuery.fn.extend({ 
 93         queue: function (type, data) { 
 94             var setter = 2; 
 95  
 96             if (typeof type !== 'string') { 
 97                 data = type; 
 98                 type = 'fx'; 
 99                 setter--; 
100             } 
101  
102             /* 
103             当满足这个条件的有以下几个情况: 
104             1.没有参数 
105             2.参数只有一个,且type是字符串 
106              */ 
107             if (arguments.length < setter) { 
108                 return jQuery.queue(this[0], type); 
109             } 
110  
111             // 其他情况 
112             return data === undefined ? 
113                 this : 
114                 this.each(function () { 
115                     var queue = jQuery.queue(this, type, data); 
116  
117                     jQuery._queueHooks(this, type); 
118  
119                     // 如果是动画队列且第一个元素不是"inprogres", 
120                     // 就出列并执行下一个元素 
121                     if (type === 'fx' && queue[0] !== 'inprogress') { 
122                         jQuery.dequeue(this, type); 
123                     } 
124                 }); 
125         }, 
126         dequeue: function (type) { 
127             return this.each(function () { 
128                 jQuery.dequeue(this, type); 
129             }); 
130         }, 
131         // TODO 
132         delay: function (time, type) { 
133             time = jQuery.fx ? jQuery.fx.speeds[time] || time : time; 
134             type = type || 'fx'; 
135  
136             return this.queue(type, function (next, hooks) { 
137                 var timeout = setTimeout(next, time); 
138                 hooks.stop = function () { 
139                     clearTimeout(timeout); 
140                 }; 
141             }); 
142         }, 
143         clearQueue: function (type) { 
144             return this.queue(type || 'fx', []); 
145         }, 
146         promise: function (type, obj) { 
147             var tmp, 
148                 count = 1, 
149                 defer = jQuery.Deferred(), 
150                 elements = this, 
151                 i = this.length, 
152                 resolve = function () { 
153                     if (!(--count)) { 
154                         defer.resolveWith(elements, [elements]); 
155                     } 
156                 }; 
157  
158             if (typeof type !== 'string') { 
159                 obj = type; 
160                 type = undefined; 
161             } 
162             type = type || 'fx'; 
163  
164             while (i--) { 
165                 tmp = jQuery._data(elements[i], type + 'queueHooks'); 
166                 if (tmp && tmp.empty) { 
167                     count++; 
168                     tmp.empty.add(resolve); 
169                 } 
170             } 
171             resolve(); 
172             return defer.promise(obj); 
173         } 
174     });
View Code

本文参考链接:https://www.cnblogs.com/webFrontDev/p/3141050.html