1. 程式人生 > >解密jQuery核心 DOM操作方法(二)html,text,val

解密jQuery核心 DOM操作方法(二)html,text,val

回顧下幾組DOM插入有關的方法

innerHTML 設定或獲取位於物件起始和結束標籤內的 HTML
outerHTML 設定或獲取物件及其內容的 HTML 形式

看圖對照區別

image

innerText 設定或獲取位於物件起始和結束標籤內的文字
outerText 設定(包括標籤)或獲取(不包括標籤)物件的文字

image


innerText 和outerText 在讀取得時候是一樣的,只是在設定的時候outerText 會連帶標籤一起替換成目標文字
firefox不支援innerText ,但是可以用textContent作為替代方案。

nodeValue


對於文字節點,nodeValue 屬性包含文字。

對於屬性節點,nodeValue 屬性包含屬性值。

nodeValue 屬性對於文件節點和元素節點是不可用的。

jQuery封裝的方法html,text,val

  1. .html()用為讀取和修改元素的HTML標籤
  2. .text()用來讀取或修改元素的純文字內容
  3. .val()用來讀取或修改表單元素的value值。

.html()

獲取集合中第一個匹配元素的HTML內容 或 設定每一個匹配元素的html內容

取值

獲取集合中第一個匹配元素的HTML內容

在一個 HTML 文件中, 我們可以使用 .html()

方法來獲取任意一個元素的內容。 如果選擇器匹配多個元素,那麼只有第一個匹配元素的 HTML 內容會被獲取

原始碼部分可見jQuery.access在屬性節點操作的時候就詳解過了,就是合併分解多個引數,細分到每一個流程呼叫中,通過回撥接收分解後的引數

可見針對nodeType === 1的節點是通過瀏覽器介面innerHTML返回需要取的值

有些瀏覽器返回的結果可能不是原始文件的 HTML 原始碼。例如,如果屬性值只包含字母數字字元,Internet Explorer有時丟棄包裹屬性值的引號。

html: function( value ) {
        return jQuery.access( this
, function( value ) { var elem = this[ 0 ] || {}, i = 0, l = this.length; if ( value === undefined && elem.nodeType === 1 ) { return elem.innerHTML; } }, null, value, arguments.length );

設值

.html() 方法對 XML 文件無效.

我們可以使用 .html() 來設定元素的內容,這些元素中的任何內容會完全被新的內容取代。

此外,用新的內容替換這些元素前,jQuery從子元素刪除其他結構,如資料和事件處理程式,防止記憶體溢位

if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
    !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) {
    value = value.replace( rxhtmlTag, "<$1></$2>" );
    try {
        for ( ; i < l; i++ ) {
            elem = this[ i ] || {};

            // Remove element nodes and prevent memory leaks
            if ( elem.nodeType === 1 ) {
                jQuery.cleanData( getAll( elem, false ) );
                elem.innerHTML = value;
            }
        }
        elem = 0;
        // If using innerHTML throws an exception, use the fallback method
    } catch( e ) {}
}

對插入的值做一下過濾處理

必須是字串,而且不能暴行script|style|link,並且不是tr,表格等元素

最後通過innerHTML覆蓋節點,防止記憶體溢位需要jQuery.cleanData清理節點上的事件與資料

總結

elem.innerHTML 也就是從物件的起始位置到終止位置的全部內容,包括Html標籤。

.text()

得到匹配元素集合中每個元素的文字內容結合,包括他們的後代,或設定匹配元素集合中每個元素的文字內容為指定的文字內容。

.text() 在XML 和 HTML 文件中都能使用。.text() 方法返回一個字串,包含所有匹配元素的合併文字。  (由於在不同的瀏覽器中的HTML解析器的變化,返回的文字中換行和其他空白可能會有所不同。)

text: function( value ) {
    return jQuery.access( this, function( value ) {
        return value === undefined ?
            jQuery.text( this ) :
            this.empty().append( ( this[ 0 ] && this[ 0 ].ownerDocument || document ).createTextNode( value ) );
    }, null, value, arguments.length );
},

取值

 jQuery.text( this ) 實際呼叫Sizzle.getText

if ( typeof elem.textContent === "string" ) {
                    return elem.textContent;
                } else {
                    // Traverse its children
                    for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
                        ret += getText( elem );
                    }
                }

但是實際上jQuery沒有用innerText獲取文字的值,

所以jQuery採用了textContent獲取文字值,textContent本身是dom3規範的,可以相容火狐下的innerText問題

設值

考慮下,如果文字的值不僅僅是字串,可能是帶有標籤的

'<p>This is a test.</p>'

這種情況下,當然就不能直接套用 elem.textContent = '<p>This is a test.</p>'

我們必須意識到這種方法提供了必要的字串從提供的正確的HTML中脫離出來。

jQuery這樣做, 他呼叫DOM 方法.createTextNode(), 一種替代的特殊字元與HTML對應(比如< 替換為 &lt; )方法

看程式碼

this.empty().append( ( this[ 0 ] && this[ 0 ].ownerDocument || document ).createTextNode( value ) );

通過empty,先清理該節點上的事件與內容

// Prevent memory leaks
                    jQuery.cleanData( getAll( elem, false ) );
                    // Remove any remaining nodes
                    elem.textContent = "";

通過createTextNode處理,呼叫append

總結

.text() 在XML 和 HTML 文件中都能使用。.text() 方法返回一個字串,包含所有匹配元素的合併文字。  (由於在不同的瀏覽器中的HTML解析器的變化,返回的文字中換行和其他空白可能會有所不同。

.text() 方法不能使用在 input 元素或scripts元素上。 inputtextarea 需要使用 .val() 方法獲取或設定文字值。得到scripts元素的值,使用.html()方法

.val()

獲取匹配的元素集合中第一個元素的當前值或設定匹配的元素集合中每個元素的值。

.val()方法主要用於獲取表單元素的值,比如 input, selecttextarea

取值

hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];

                    if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
                        return ret;
                    }

                    ret = elem.value;

                    return typeof ret === "string" ?
                        // handle most common string cases
                        ret.replace(rreturn, "") :
                        // handle cases where value is null/undef or number
                        ret == null ? "" : ret;

select為例

<select multiple="multiple"> 元素, .val()方法返回一個包含每個選擇項的陣列,如果沒有選擇性被選中,它返回null

html程式碼,multiple="multiple" 多選項,如果只是單選,只用用ele.value即可了

<select size="10" multiple="multiple" id="multipleselect" name="multipleselect">
    <option>XHTML</option>
    <option>CSS</option>
    <option>JAVASCRIPT</option>
    <option>XML</option>
    <option>PHP</option>
    <option>C#</option>
    <option>JAVA</option>
    <option>C++</option>
    <option>PERL</option>
</select>

js程式碼

var p = $("#multipleselect")
     p.change(function(){
         console.log( p.val());
     });

image

針對多選的情況,jQuery要如何處理?

引入了jQuery.valHooks,修正了在不同情況下表單取值的bug,其中就有針對select的set與get的處理

image

針對多選的hack

for ( ; i < max; i++ ) {
                        option = options[ i ];

                        // IE6-9 doesn't update selected after form reset (#2551)
                        if ( ( option.selected || i === index ) &&
                            // Don't return options that are disabled or in a disabled optgroup
                            ( jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) &&
                            ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {

                            // Get the specific value for the option
                            value = jQuery( option ).val();

                            // We don't need an array for one selects
                            if ( one ) {
                                return value;
                            }

                            // Multi-Selects return an array
                            values.push( value );
                        }
                    }

遍歷所有的option元素,找到對應的value

option: {
                get: function( elem ) {
                    // attributes.value is undefined in Blackberry 4.7 but
                    // uses .value. See #6932
                    var val = elem.attributes.value;
                    return !val || val.specified ? elem.value : elem.text;
                }
            }

如果是多選

values.push( value ); 

返回合集

設值

同樣的處理類似,通過jQuery.valHooks找到對應的處理hack

否則直接 this.value = val;