jQuery 源碼分析(十一) 隊列模塊 Queue詳解

来源:https://www.cnblogs.com/greatdesert/archive/2019/10/16/11670591.html
-Advertisement-
Play Games

隊列是常用的數據結構之一,只允許在表的前端(隊頭)進行刪除操作(出隊),在表的後端(隊尾)進行插入操作(入隊)。特點是先進先出,最先插入的元素最先被刪除。 在jQuery內部,隊列模塊為動畫模塊提供基礎功能,負責存儲動畫函數、自動出隊並執行動畫函數,同時還要確保動畫函數的順序執行。 jQuery的靜 ...


隊列是常用的數據結構之一,只允許在表的前端(隊頭)進行刪除操作(出隊),在表的後端(隊尾)進行插入操作(入隊)。特點是先進先出,最先插入的元素最先被刪除。

在jQuery內部,隊列模塊為動畫模塊提供基礎功能,負責存儲動畫函數、自動出隊並執行動畫函數,同時還要確保動畫函數的順序執行。

jQuery的靜態方法含有如下API:

  • $.queue(elem,type,data) ;返回或修改匹配元素關聯的隊列,返回最新的隊列,參數如下:

                  elem   ;DOM元素或JavaScript對象

                type   ;隊列名稱,預設是標準動畫fx

                data  ;需要設置的隊列函數,可以是空(返回隊列)、函數(加入隊列)或函數數組(替換隊列)

  • $.dequeue(elem,type)   ;用於出隊並執行匹配元素關聯的函數隊列中的下一個元素

                elem  ;DOM元素或JavaScript對象

                type  ;是隊列名稱,預設為動畫隊列fx

 writer by:大沙漠 QQ:22969969

jQuery/$ 實例方法(可以通過jQuery實例調用的):

  • queue(type,data)        ;返回第一個匹配元素的函數隊列,或修改所有匹配的元素關聯的函數隊列,參數如下:

                type  ;隊列名稱

                data  ;data是可選的函數或函數數組,參數同$.queue()的第三個參數

  • dequeue(type)       ;出隊並執行所有匹配元素關聯的函數隊列中的下一個函數
  • delay(time,type)          ;延遲函數出隊執行。通過調用.queue(type,data)向關聯的函數隊列中插入一個新的函數,在函數內通過setTimeout()延遲下一個函數的出隊時間。
  • clearQueue(type)          ;移除匹配元素關聯的函數隊列中的所有未被執行的函數,內部代碼就一句:return this.queue( type || "fx", [] );

舉個慄子:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script src="http://libs.baidu.com/jquery/1.7.1/jquery.min.js"></script>
</head>
<body>
    <p>123</p>
    <script>
        function f1(){console.log('f1觸發');}    //定義兩個測試函數
        function f2(){console.log('f2觸發')};

        $('p').queue('test',f1);                 //將f1入隊,隊列名稱為test
        $('p').dequeue('test');                //將匹配元素的名稱為test的函數列表出隊並執行
        $('p').queue(f2);                    //將f2放入p匹配元素的隊列中,預設為動畫隊列,會自動執行。
    </script>    
</body>
</html>

輸出如下:

 

源碼分析


jQuery的隊列是基於數據緩存模塊$.data來實現的,當調用$.queue()時回把函數列表以隊列名+'queue'為屬性,保存在對應的DOM元素的內部緩存對象上,例如:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script src="http://libs.baidu.com/jquery/1.7.1/jquery.min.js"></script>
</head>
<body>
    <p>123</p>
    <script>
        function f1(){console.log('f1觸發');}
        $('p').queue('test',f1);    
    </script>    
</body>
</html>

我們可以在控制台里直接從$.cache里獲取對應的屬性,如下:

 document.getElementsByTagName('p')[0][$.expando]就是例子里p元素節點對象的$.expando屬性,該屬性的值會作為$.cache的某個屬性,存儲著對應這個p元素的數據緩存對象(這是數據緩存模塊的內容)

$.queue和$.dequeue的實現如下:

jQuery.extend({
    /**/
    queue: function( elem, type, data ) {            //返回或修改匹配元素關聯的隊列。elem是DOM元素或JavaScript對象,type是隊列名稱,data是可選的函數或函數數組
        var q;
        if ( elem ) {
            type = ( type || "fx" ) + "queue";                //修正參數type,預設為動畫隊列fx,在參數type後面加上queue表示這是一個隊列
            q = jQuery._data( elem, type );                    //取出參數type對應的隊列 如果之前有數據則返回該數組 否則 q等於undefined

            // Speed up dequeue by getting out quickly if this is just a lookup
            if ( data ) {                                    //如果傳入了data參數
                if ( !q || jQuery.isArray(data) ) {                //如果type隊列不存在,或者type隊列存在且data是一個數組
                    q = jQuery._data( elem, type, jQuery.makeArray(data) );    //調用jQuery.makeArray把參數data轉換為數組並替換隊列
                } else {
                    q.push( data );                                //隊列存在且data不是一個數組則調用數組push方法把參數data放入隊列
                }
            }
            return q || [];
        }
    },

    dequeue: function( elem, type ) {                //用於出隊並執行匹配元素關聯的函數隊列中的下一個元素
        type = type || "fx";                            //修正參數type,預設是"fx";

        var queue = jQuery.queue( elem, type ),            //獲取elem元素的type隊列
            fn = queue.shift(),                            //調用shift方法取出隊列第一個函數
            hooks = {};                                    //存放出隊的函數在執行時的數據

        // If the fx queue is dequeued, always remove the progress sentinel
        if ( fn === "inprogress" ) {                    //如果出隊的是占位符"inprogress",則丟棄再從隊列頭部出一個,只有動畫隊列會設置占位符"inprogress"
            fn = queue.shift();
        }

        if ( fn ) {
            // Add a progress sentinel to prevent the fx queue from being
            // automatically dequeued
            if ( type === "fx" ) {                        //如果是動畫隊列
                queue.unshift( "inprogress" );                //則在隊列開頭添加一個占位符"inprogress",表示動畫函數正在執行當中
            }

            jQuery._data( elem, type + ".run", hooks );    //設置內部數據type+".run",表示參數type對應的隊列正在執行,值是hooks,它會被作為第二個參數傳遞給出隊的函數
            fn.call( elem, function() {
                jQuery.dequeue( elem, type );
            }, hooks );                                    //調用函數方法call執行出隊的函數,elem是函數執行的上下文,即關鍵詞this指向的對象;第二個參數是封裝了jQuery.dequeue( elem, type )的函數,不會自動執行,需要在出隊的函數返回前手動調用next()
        }

        if ( !queue.length ) {                            //如果參數type對應的隊列在出隊後成為空隊列,即所有函數都已經出隊並執行
            jQuery.removeData( elem, type + "queue " + type + ".run", true );        //調用jQuery.removeData()方法移除參數type對應的數據緩存對象
            handleQueueMarkDefer( elem, type, "queue" );                            //檢查匹配元素關聯的隊列(type+"queue")和計數器(type+"mark")是否完成,如果完成則觸發方法.promise()中的計數器
        }
    }
});

type預設等於fx,jQuery的動畫效果也是基於Queue實現的,這個fx預設就是動畫效果,對於jQuery/$ 實例方法來說,它是調用jQuery的靜態方法來實現的,如下:

jQuery.fn.extend({
    queue: function( type, data ) {            //返回第一個匹配元素的函數隊列,或修改所有匹配的元素關聯的函數隊列。type是隊列名稱,預設是fx。data參數等同於jQuery.queue中的data參數
        if ( typeof type !== "string" ) {        //修正參數    當傳入的格式是queue()或queue(data) (註:data可以是函數或函數數組)時
            data = type;
            type = "fx";
        }

        if ( data === undefined ) {                //如果沒有傳入data參數,
            return jQuery.queue( this[0], type );    //則調用jQuery.queue()返回第一個匹配元素上參數type對應的隊列
        }
        return this.each(function() {            //如果傳入了data參數
            var queue = jQuery.queue( this, type, data );        //為每一個匹配元素調用jQuery.queue( this, type, data ),把參數(函數)入隊,或者用參數data(函數數組)替換隊列。

            if ( type === "fx" && queue[0] !== "inprogress" ) {    //對於動畫隊列fx,且沒有動畫函數正在執行,則立即出隊並執行動畫函數。
                jQuery.dequeue( this, type );
            }
        });
    },
    dequeue: function( type ) {                    //出隊並執行匹配元素關聯的函數隊列中的下一個函數
        return this.each(function() {
            jQuery.dequeue( this, type );
        });
    },
    /**/
})

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 概述 數據完整性指資料庫中數據的 正確性、相容性和一致性 。包括現實世界中的應用需求的完整性。數據的完整性由完整性規則來定義。 關係模型的完整性規則是對關係的某種約束,提供一種手段來保證用戶對資料庫的修改時不會破壞資料庫中數據的完整性。保證數據是有意義的。 關係模型分三類約束:實體完整性約束、參照完 ...
  • 在SQL Server中重建索引(Rebuild Index)與重組索引(Reorganize Index)會觸發統計信息更新嗎? 那麼我們先來測試、驗證一下: 我們以AdventureWorks2014為測試環境,如下所示: Person.Person表的統計信息最後一次更新為2014-07-17... ...
  • 本文基於 Android 9.0 , 代碼倉庫地址 : "android_9.0.0_r45" 文中源碼鏈接: "SystemServer.java" "ActivityManagerService.java" "Process.java" "ZygoteProcess.java" 對 和 啟動流程 ...
  • 1. 在對象內部讀取數據時,應該直接通過實例變數來讀,而寫入數據時,則應通過屬性來寫。 2. 在初始化方法及dealloc方法中,總是應該直接通過實例變數來讀寫數據。 3. 使用Lazy Initialization配置的數據,應該通過屬性來讀取數據。 4. 不要在setter/g... ...
  • 1. 可以用@property語法來定義對象中所封裝的數據。 2. 通過“修飾詞”來指定存儲數據所需的正確語義。 3. 在設置屬性所對應的實例變數時,一定要遵從該屬性所聲明的語義。 4. 開發iOS程式時應該使用nonatomic屬性,因為atomic(同步鎖)屬性嚴重影響性能。 ...
  • 1. 應該用枚舉表示狀態機的狀態、傳遞給方法的選項以及狀態碼等值,給這些值起個易懂的名字,就像監聽網路狀態的枚舉。 2. 如果把傳遞給某個方法的選項表示為枚舉類型,而多個選項又可同時使用,那麼就將各選項定義為2的冪,以便通過按位或操作將其組合起來。 3. 用 NS_ENUM 與 NS_O... ...
  • 本篇記錄的是使用Jsoup框架爬取網頁內容,結合Android的RecyclerView,從而實現批量下載小說的功能(也是我的APP "星之小說下載器Android版" 的核心功能), 思路僅供參考 本文使用了AsyncTask來實現下載功能,不懂使用的可以參考一下我的文章 "Android開發—— ...
  • 換膚思路: 1.什麼時候換膚? xml載入前換膚,如果xml載入後換膚,用戶將會看見換膚之前的色彩,用戶體驗不好。 2.皮膚是什麼? 皮膚就是apk,是一個資源包,包含了顏色、圖片等。 3.什麼樣的控制項應該進行換膚? 包含背景圖片的控制項,例如textView文字顏色。 4.皮膚與已安裝的資源如何匹配 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...