萬盛學電腦網

 萬盛學電腦網 >> 腳本專題 >> javascript >> jQuery內核 DOM詳細操作

jQuery內核 DOM詳細操作

 domManip是什麼

dom即Dom元素,Manip是Manipulate的縮寫,連在一起就是Dom操作的意思。

jQuery針對DOM操作的插入的方法有大概10種

append、prepend、before、after、replaceWith

appendTo、prependTo、insertBefore、insertAfter、replaceAll

分2組,上下對照,實現同樣的功能。主要的不同是語法——特別是內容和目標的位置

依賴的domManip,buildFragment模塊在之前就分析過了

在匹配元素集合中的每個元素後面插入參數所指定的內容,作為其兄弟節點

對於 .after(), 選擇表達式在函數的前面,參數是將要插入的內容。

對於.insertAfter(), 剛好相反,內容在方法前面,它將被放在參數裡元素的後面。

after

after: function() {    return this.domManip( arguments, function( elem ) 
{        if ( this.parentNode )
 {            this.parentNode.insertBefore( elem, this.nextSibling );
        }
    });
},

之前提過了所有的方法靠this.domManip合並參數處理,內部通過buildFragment模塊構建文檔碎片

然後把每一個方法的具體執行通過回調的方式提供出來處理

DOM操作並未提供一個直接可以在當前節點後插入一個兄弟節點的方法,但是提供了一個類似的方法

insertBefore() 方法:可在已有的子節點前插入一個新的子節點。語法 :insertBefore(newchild,refchild)

看看jQuery如何處理的

例如

inner.after('<p>Test</p>');

內部就會把  '<p>Test</p>' 通過buildFragment構建出文檔elem

然後通過  this.parentNode.insertBefore( elem, this.nextSibling );

這裡的this 就是對應著inner ,elem就是‘<p>Test</p>’

看到這裡就很好理解了after的實現了

用原生方法簡單模擬

var  inner = document.getElementsByClassName('inner')for(var i =0 ; i<inner.length;i++)
{    var elem = inner[i]    var div = document.createElement('div')
    div.innerHTML = 'aaaa'
    elem.parentNode.insertBefore(div,elem.nextSibling)
}

insertAfter

jQuery代碼的設計者很聰明的,都盡可能的合並相似功能的方法,代碼更加精煉美觀

jQuery.each({
    appendTo: "append",
    prependTo: "prepend",
    insertBefore: "before",
    insertAfter: "after",
    replaceAll: "replaceWith"}, function( name, original ) {
    jQuery.fn[ name ] = function( selector ) {
                           
    };
});

DEMO

$('<p>Test</p>').insertAfter('.inner');

通過$('<p>Test</p>')構建一個文檔,對象通過insertAfter方法插入到所有class等於inner的節點後

表達的意思與after是一樣的,主要的不同是語法——特別是內容和目標的位置

jQuery.fn[ name ] = function( selector ) {        var elems,
            ret = [],
            insert = jQuery( selector ),
            last = insert.length - 1,
            i = 0;        for ( ; i <= last; i++ ) {
            elems = i === last ? this : this.clone( true );
            jQuery( insert[ i ] )[ original ]( elems );  
          // Support: QtWebKit
            // .get() because core_push.apply(_, arraylike) throws 
           core_push.apply( ret, elems.get() );
        }        return this.pushStack( ret );
    };

看具體的實現方法中.insertAfter('.inner');inner其實就被當作selector傳入進來了

selector可能只是字符串選擇器內部就需要轉化,insert = jQuery( selector ),

$('<p>Test</p>')就是構建出來的文檔碎片節點,那麼如果賦給insert有多個的時候就需要完全克隆一份副本了,所以就直接賦給

elems = i === last ? this : this.clone( true ); jQuery( insert[ i ] )[ original ]( elems );

依舊是執行after

jQuery( insert[ i ] )[ original ]( elems );

最終還需要返回這個構建的新節點

收集構建的節點

core_push.apply( ret, elems.get() );

構建一個新jQuery對象,以便實現鏈式

this.pushStack( ret );

可見after 與 insertAfter 本質本質其實都是一樣的,只是通過不同的方式調用

before()

根據參數設定,在匹配元素的前面插入內容

before: function() {        return this.domManip( arguments, function( elem )
 {            if ( this.parentNode )
 {                this.parentNode.insertBefore( elem, this );
            }
        });
    },

類似after只是替換了第二個參數,改變插入的位置

append()

在每個匹配元素裡面的末尾處插入參數內容

append: function() {    return this.domManip( arguments, function( elem )

{        if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 )

{            var target = manipulationTarget( this, elem );

            target.appendChild( elem );
        }
    });
},

內部增加節點,直接可以調用appendChild方法

prepend()

將參數內容插入到每個匹配元素的前面(元素內部)

prepend: function() {    return this.domManip( arguments, function( elem )
 {        if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 )
 {            var target = manipulationTarget( this, elem );
            target.insertBefore( elem, target.firstChild );
        }
    });
},

類似after只是替換了第二個參數,改變插入的位置

replaceWith()

用提供

copyright © 萬盛學電腦網 all rights reserved