jQuery 源碼解析(二十四) DOM操作模塊 包裹元素 詳解

来源:https://www.cnblogs.com/greatdesert/archive/2019/11/15/11820454.html
-Advertisement-
Play Games

本節說一下DOM操作模塊里的包裹元素子模塊,該模塊可將當前匹配的元素替換指定的DOM元素,有如下方法: wrap(html) ;在每個匹配元素的外層添加一層DOM元素 ;該方法會遍歷匹配元素集合,在每個元素上調用.wrapAll()方法 ;不同於wrapAll()的是該方法會在每個匹配元素外面都套一 ...


本節說一下DOM操作模塊里的包裹元素子模塊,該模塊可將當前匹配的元素替換指定的DOM元素,有如下方法:

  • wrap(html)               ;在每個匹配元素的外層添加一層DOM元素                                ;該方法會遍歷匹配元素集合,在每個元素上調用.wrapAll()方法        ;不同於wrapAll()的是該方法會在每個匹配元素外面都套一層html元素。
  • wrapAll(html)            ;會將html轉化為一個DOM節點並放在第一個匹配元素的前面,再把其他匹配元素也依次放進去    ;html可以是html片段、選擇器表達式、jQuery對象、DOM元素或函數,下同。
  • wrapInner(html)        ;在每個匹配元素的內容前後包裹HTML元素    ;該方法會遍歷匹配元素集合,並通過調用方法.wrapAll()為每個匹配元素的所有內容包裹一段HTML結構。
  • unwrap()                  ;移除匹配元素集合中每個元素的父標簽,並把匹配元素留在父元素的位置上

舉個慄子:

 writer by:大沙漠 QQ:22969969

<!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>你好</p>
    <p>Hello World</p>
    <div>
        <i>
            <span>測試文本</span>
        </i>
    </div>

    <button id="b1">按鈕1</button> <br/>
    <button id="b2">按鈕2</button><button id="b3">按鈕3</button> <br/>
    <button id="b4">按鈕4</button><br/><button id="b5">按鈕5</button>
    <script>
        b1.onclick=function(){$('p').wrap('<div></div>')}              //內部將<div></div>轉化為jQuery對象放到第一個匹配元素<p>你好</p>之前,再將匹配元素移動到該DOM節點內部

        b2.onclick=function(){$('p').wrapAll('<div></div>')}           //內部將<div></div>轉化為jQuery對象放到第一個匹配元素<p>你好</p>之前,再將匹配元素移動到該DOM節點內部
        b3.onclick=function(){$('p').wrapAll('<div><p></p></div>')}    //如果含有子節點,則會將匹配元素移動到子節點裡面

        b4.onclick=function(){$('p').wrapInner('<div></div>')}         //在每個匹配元素的內容前後添加一層DOM節點(包裹層)

        b5.onclick=function(){$('span').unwrap() }                     //移除每個匹配元素的父元素,並讓匹配元素占有該節點位置
    </script>
</body>
</html>

渲染如下:

 對應的DOM樹如下:

 點擊按鈕1會在所有的P標簽上加一個div父節點,如下:

 點擊按鈕2將在第一個p標簽前添加一個div,然後把所有p標簽放到div之下,如下:

 點擊按鈕3將在第一個p標簽前添加一個div>p雙層DOM,然後把所有p標簽放到div之下,如下:

 點擊按鈕4將在p標簽內最外層嵌套一層div標簽,如下:

 點擊按鈕5將會去除 span的上一層DOM節點,如下:

 如果再次點擊,會將span的上一層DOM繼續移除,直到遇到body節點為止

 

源碼分析


wrapInner和wrap都是基於wrapAll實現的,wrapAll實現如下:

jQuery.fn.extend({
    wrapAll: function( html ) {                //在匹配的元素外面放置html元素。html參數可以是html片段、選擇器表達式、jQuery對象、DOM元素或函數。
        if ( jQuery.isFunction( html ) ) {        //如果html是函數
            return this.each(function(i) {
                jQuery(this).wrapAll( html.call(this, i) );    //遍歷匹配元素,在每個匹配元素上執行html函數,並用該函數的返回值作為參數迭代調用.wrapAll()函數。
            });
        }

        if ( this[0] ) {                        //如果當前有匹配元素
            // The elements to wrap the target around
            var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);        //將html轉化為一個jQuery對象

            if ( this[0].parentNode ) {                                                //如果當前第一個匹配元素有父元素,
                wrap.insertBefore( this[0] );                                            //則把創建的包裹元素插入第一個匹配元素之前。
            }

            wrap.map(function() {                            //遍歷wrap元素
                var elem = this;                                //elem是創建的包裹元素的引用

                while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {    //如果html里含有一個子節點
                    elem = elem.firstChild;                                            //則重置elem為html的子節點,上面的按鈕3會執行到這裡
                }

                return elem;
            }).append( this );                                    //這一行的this是當前匹配的jQuery對象,把每個匹配元素移動到插入的元素之後
        }

        return this;
    },
})

wrapAll首先會把參數轉化為一個jQuery對象,然後插入到當前第一個匹配元素的前面,最後以生成的jQuery對象為主句,調用append()將當前匹配匹配的所有元素添加到新生成的jQuery對象對應的DOM節點內部。對應上面的按鈕2

wrap()實現如下:

jQuery.fn.extend({
    wrap: function( html ) {                //在每個匹配元素的外層添加一層DOM元素
        var isFunction = jQuery.isFunction( html );        //在每個匹配元素前後包裹一段HTML結構,該方法會遍歷匹配元素集合,在每個元素上調用.wrapAll()方法。
        return this.each(function(i) {
            jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );    //依次調用wrapALl()函數
        });
    },
})

wrapInner的實現如下:

jQuery.fn.extend({
    wrapInner: function( html ) {            //用於在匹配元素集合中每個元素的內容前後包裹一段HTML結構,該方法會遍歷匹配元素集合
        if ( jQuery.isFunction( html ) ) {                //如果html是函數
            return this.each(function(i) {
                jQuery(this).wrapInner( html.call(this, i) );    //遍歷匹配元素,在每個匹配元素上執行html函數,並用該函數的返回值作為參數迭代調用.wrapInner()函數。
            });
        }

        return this.each(function() {                    //遍歷匹配元素集合
            var self = jQuery( this ),
                contents = self.contents();                    //先獲取所有子節點

            if ( contents.length ) {                        //如果有子節點
                contents.wrapAll( html );                        //調用wrapAll(html)為當前元素的所有內容包裹一段HTML代碼。
            } else {
                self.append( html );                        //如果當前元素沒有內容,則直接將參數html插入當前內容。
            }
        });
    },
})

unwrap的實現如下:

Query.fn.extend({
    unwrap: function() {                        //移除匹配元素集合中每個元素的父標簽,並把匹配元素留在父元素的位置上
        return this.parent().each(function() {            //先遍歷父節點
            if ( !jQuery.nodeName( this, "body" ) ) {        //如果不是body元素
                jQuery( this ).replaceWith( this.childNodes );    //則調用replaceWith將this.childNodes替換為this,註意,這裡的this上下文是父節點
            }
        }).end();
    }
})

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

-Advertisement-
Play Games
更多相關文章
  • 1、啟動頁面:index.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <title>hc ...
  • 元素的顯示與隱藏 1. 本質:讓一個元素在頁面中隱藏或顯示出來 2. display:顯示隱藏 用於設置一個元素應如何顯示 display:none;隱藏對象 display:block;隱藏對象 【註意】 display隱藏元素後,不在占有原來的位置 3. visibility:顯示隱藏 visi ...
  • HTTP狀態碼分類 1XX ——信息,伺服器收到請求,需要請求者繼續執行操作 2XX——成功,操作被成功接收並處理 3XX——重定向,需要進一步的操作以完成請求 4XX——客戶端錯誤,請求包含語法錯誤或者無法完成請求 5XX——伺服器錯誤,伺服器在處理請求的過程中發生了錯誤 2XX狀態碼 | 狀態碼 ...
  • 事件發生時會在元素節點之間按照特定的順序傳播,這個傳播過程即DOM事件流。 DOM事件流分為三個階段,分別為: 捕獲階段:事件從Document節點自上而下向目標節點傳播的階段; 目標階段:真正的目標節點正在處理事件的階段; 冒泡階段:事件從目標節點自上而下向Document節點傳播的階段。 捕獲階 ...
  • 一、載入 ui element vue add element 載入過程及成功結果如下 > vue add element> �� Installing vue-cli-plugin-element... > + [email protected] > added 1 pack ...
  • 在安裝vue-cli之前,要先安裝node.js這個大家百度一下就可以了 1、安裝 vue-cli npm install -g @vue/cli-init 2、初始化一個項目,名為 hcmanage ,並選擇使用 webpack 打包方式 vue init webpack hcmanage 3、切 ...
  • 一、環境安裝 Node.js 安裝包及源碼下載地址為: "https://nodejs.org/en/download/" 。 在該頁面你可以根據不同平臺系統選擇你需要的 Node.js 安裝包。 Node.js裡面集成了npm,npm是一種包管理工具,允許用戶從NPM伺服器下載別人編寫的包或命令行 ...
  • 動畫是CSS3中具有顛覆性的特征之一,可通過設置多個節點來精確控制一個或一組動畫,常用來實現複雜的動畫效果。 語法格式: animation:動畫名稱 花費時間 運動曲線 何時開始 播放次數 是否反方向; 關於幾個值,除了名字,動畫時間,延時有嚴格順序要求其它隨意r @keyframes 動畫名稱 ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...