解密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獲取文本的值,

http://bugs.jquery.com/ticket/11153,大概就是在IE8中新節點插入會保留所有回車

所以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

對於選擇框和復選框,您也可以使用:selected:checked選擇器來獲取值,

取值

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;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM