domManip是什么
dom即Dom元素,Manip是Manipulate的縮寫,連在一起就是Dom操作的意思。
.domManip()是jQuery DOM操作的核心函數
對封裝的節點操作做了參數上的校正支持,與對應處理的調用
append、prepend、before、after、replaceWith
appendTo、prependTo、insertBefore、insertAfter、replaceAll
為什么需要用這個domManip函數呢?
我們知道節點操作瀏覽器提供的接口無非就是那么幾個
appendChild()
通過把一個節點增加到當前節點的childNodes[]組,給文檔樹增加節點。
cloneNode()
復制當前節點,或者復制當前節點以及它的所有子孫節點。
hasChildNodes()
如果當前節點擁有子節點,則將返回true。
insertBefore()
給文檔樹插入一個節點,位置在當前節點的指定子節點之前。如果該節點已經存在,則刪除之再插入到它的位置。
removeChild()
從文檔樹中刪除並返回指定的子節點。
replaceChild()
從文檔樹中刪除並返回指定的子節點,用另一個節點替換它。
以上接口都有一個特性,傳入的是一個節點元素
如果我們傳遞不是一個dom節點元素,如果是一個字符串,一個函數或者其他呢,所以針對所有接口的操作,jQuery會抽象出一種參數的處理方案
也就是domManip存在的意義了,針對很多類似接口的參數抽象jQuery內部有很多這樣的函數了,如之前屬性操作中的jQuery.access
jQuery支持的參數傳遞
jquery對接點才操作封裝出了一系列的接口,可以接受HTML字符串,DOM 元素,元素數組,或者jQuery對象,用來插在集合中每個匹配元素的不同位置
例如
HTML結構
$('.inner').after('<p>Test</p>');
$對象
$('.container').after($('h2'));
回調函數
一個返回HTML字符串,DOM 元素, 或者 jQuery 對象的函數,插在每個匹配元素的后面。接收元素在集合中的索引位置作為參數。在函數中this
指向元素集合中的當前元素
$('p').after(function() { return '<div>' + this.className + '</div>'; });
domManip源碼
針對節點的操作有幾個重點的細節
- 保證最終操作的永遠是dom元素,瀏覽器的最終API只認識那么幾個接口,所以如果傳遞是字符串或者其他的,當然需要轉換
- 針對節點的大量操作,我們肯定是需要引入文檔碎片做優化的,這個必不可少
domManip的結構
傳遞的參數, 對應的處理回調,節點是否替換
domManip: function( args, callback, allowIntersection ) {
參數初始化
iNoClone = l - 1, 是否為克隆節點,根據后面的大意,如果當前的jQuery對象是一個合集對象花
那么意味着通過文檔碎片構件出來的dom,只能是副本克隆到每一個合集對象中
value 是第一個元素,后邊只針對args[0]進行檢測,意味着args中的元素必須是統一類型;
WebKit checked屬性
如果是回調函數,或者跳過WebKit checked屬性
在WebKit中,不能克隆包含了已選中多選按鈕的文檔碎片,這有什么問題?之后在測
文檔碎片
將html轉化成dom
其實最終是通過jQuery.buildFragment方法構件出文檔碎片
文檔碎片的好處就不用多說了,多個繪制操作的時候合並必備
插入頁面
這里就用了到iNoClone了
一看代碼就很明顯 修正了node節點, 為什么要修正?
因為通過文檔碎片構建出來的只一樣個dom,但是jQuery是一個合集對象,所以都需要用到這個碎片了,所以你把args append到第一個元素上了,jQuery實例的第二個元素他怎么辦啊?他沒有可以append的了?!所以,上來要判斷一下實例的長度是不是大於1,大於1就需要cloneNode。
callback就是對應了所有api需要執行的操作方法了
jQuery2X是高級版本,所以不兼容IE6等低級瀏覽器了,自然在IE6中插入tr,如果漏掉tbody的問題也就不需要修復了
domManip其實就只做了2事件
第一個就是判斷3種傳遞參數所映射的對應操作
第二個就是通過調用jQuery.buildFragment生成文檔碎片