jQuery屬性操做之.attr()

轉載請註明出處數組

@瀏覽器

.attr()

1..attr()的四種用法
大體用法:函數

  • 調用形式:$("xxx").attr(attrName);
    獲取匹配到的全部元素中的第一個元素的指定屬性的屬性值.
  • 調用形式:$("xxx").attr(attrName,value):
    • 設置/新增匹配到的全部元素的指定屬性的屬性值
    • 若是value=null,指定屬性將被刪除
  • 調用形式:$("xxx").attr(attrObject):
    用"屬性-值"的鍵值對構成的對象來設置匹配到的全部元素的一個或多個屬性.
  • 調用形式:$("xxx").attr(attrName,attrFn(index,val)):
    用一個函數attrFn的返回值做爲value來設置某一個匹配元素的指定屬性.(attrFn函數的參數有明確規定:index--該匹配元素在jQuery對象中的index值,也就是它的鍵值.attr--當前該元素的該屬性的值(舊值))

用法詳解:
(1)..attr()源代碼定義:this

jQuery.fn.extend( {
    attr: function( name, value ) {
        return access( this, jQuery.attr, name, value, arguments.length > 1 );
    }
}

可見,.attr的核心是函數access(),而該函數不須要實例便可調用,屬於直接定義在jQuery上的'靜態函數'.code

jQuery.access()源代碼定義:對象

var access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
    var i = 0,
        length = elems.length,
        bulk = key == null; //bulk用於判斷key值是否爲null(注:null==undefined的結果爲true)

    // 設置多個值(當key參數爲對象時,注:jQuery.type實現原理是[[class]])
    if ( jQuery.type( key ) === "object" ) {
        chainable = true;
        for ( i in key ) {
            access( elems, fn, i, key[ i ], true, emptyGet, raw );
        }

    // 設置一個值(當key爲非對象類型時)
    } else if ( value !== undefined ) {
        chainable = true;

        if ( !jQuery.isFunction( value ) ) {
            raw = true; //判斷value值是否爲函數類型.若是不是函數,設置raw值,爲if(fn)以及if(bulk)埋下伏筆
        }

        if ( bulk ) { //批處理

            // 批處理是執行在整個屬性集上的
            if ( raw ) {
                fn.call( elems, value );
                fn = null;

            // 當value爲函數時又有點不一樣
            } else {
                bulk = fn;
                fn = function( elem, key, value ) {
                    return bulk.call( jQuery( elem ), value );
                };
            }
        }

        if ( fn ) { //對elems中的每個元素應用fn方法,第三個參數由raw決定
            for ( ; i < length; i++ ) {
                fn(
                    elems[ i ],
                    key,
                    raw ? value : value.call( elems[ i ], i, fn( elems[ i ], key ) )
                );
            }
        }
    }

    return chainable ? //返回值設定
        elems :

        // Gets
        bulk ?
            fn.call( elems ) :
            length ? fn( elems[ 0 ], key ) : emptyGet;
}

如上圖,因爲access函數用途並不侷限於咱們的.attr(),做爲像筆者同樣的jQuery初學者,源代碼中有許多代碼語句咱們不能很好的理解(好比:if(bulk)部分).因爲暫時接觸到的jQuery內容較少較淺,咱們若是一味深究,可能既搞不清楚原理,還浪費時間.因此,咱們能夠用一種簡化的思想來分析問題: 只關注代碼中跟咱們當前問題有關的部分,忽略無關的,用不到的部分.遞歸

具體作法:咱們將.attr()的四種用法的實際傳參狀況帶入jQuery.access函數的定義中,刪除咱們進不去的if語句代碼塊,只保留會用到的代碼語句.索引


調用形式:$("xxx").attr(name)

attr定義:接口

attr: function( name, value=undefined ) {
    return jQuery.access( this, jQuery.attr, name, value=undefined, arguments.length > 1 );
}

access調用簡化:

var access = function( this, jQuery.attr, name, value=undefined, chainable=false, emptyGet=undefined, raw=undefined ) {
    var i = 0,
        length = this.length, //jQuery對象的length屬性(jQuery對象老是有length屬性,它是類數組對象)
        bulk = false;

    return jQuery.attr( this[0], name );
    };

一樣,咱們找到jQuery.attr()靜態方法的源代碼定義,用一樣的簡化方法分析,獲得:

jQuery.attr()完整源碼:

attr: function( elem, name, value ) {  // elem:DOM對象  name:屬性名/鍵名 value:屬性值
    var ret, hooks,
        nType = elem.nodeType;  // 節點類型

    // 屏蔽屬性節點,文本節點與註釋節點
    if ( nType === 3 || nType === 8 || nType === 2 ) {
        return; 
    }

    // 當屬性不支持getAttribute方法時,回調jQuery.prop()方法--從操做attribute變成了操做property
    if ( typeof elem.getAttribute === "undefined" ) {
        return jQuery.prop( elem, name, value );
    }


//下面的都是DOM元素elem支持getAttribute的狀況

    // 全部標籤特性(attributes)都是小寫(處理兼容:有的瀏覽器對同一屬性的名稱可能大小寫不停)
    // 若是某一個是已定義的,抓取必要的鉤子

    if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {  // 非元素節點或者是XML文本中的元素
        name = name.toLowerCase();
        hooks = jQuery.attrHooks[ name ] ||  
            ( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook ); 
    }

    if ( value !== undefined ) {//若是value在傳參時未被忽略
        if ( value === null ) {
            jQuery.removeAttr( elem, name );//傳入第三個參數爲null時,調用jQuery.removeAttr移除對應屬性
            return;
        }

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

        elem.setAttribute( name, value + "" );
        return value;
    }

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

    ret = jQuery.find.attr( elem, name );

    // 不存在的屬性會返回null,咱們將之統一爲undefined
    return ret == null ? undefined : ret;
}

jQuery.attr()簡化:

attr: function( elem, name, value=undefined ) {  // elem:DOM對象  name:屬性名/鍵名 value:屬性值
    var ret, hooks,
        nType = 1;

    ret = jQuery.find.attr( elem, name );

    return ret;
}

其中,惟一不肯定的是jQuery.find.attr,然而咱們繼續找下去則是有關Sizzle選擇器引擎的問題,這對於咱們初學者來講過於複雜.所以,咱們再簡化一下,帶入實際情景,檢測這一函數的輸出:

var $p = $('#jQueryTest')[0];

console.log(jQuery.find.attr($p,'id')); //jQueryTest

所以,大概知道該函數該種傳參狀況下的做用是返回指定DOM元素的指定屬性的值.
1.由jQuery.access簡化代碼中的return jQuery.attr( this[0], name );可知,只傳入一個name參數的狀況下,確實只會返回jQuery對象中的索引爲'0'的DOM對象的指定屬性的屬性值.
2.由jQuery.att()完整代碼中
if ( typeof elem.getAttribute === "undefined" ) {
return jQuery.prop( elem, name, value );
}

可知:若是不支持get/setAttibute,那麼原來的針對特性(attibute)的操做就會變成DOM元素屬性(property)的操做.


調用形式:$("xxx").attr(name,value);

attr定義:

attr: function( name, value) {  //此時的this是一個類數組
        return jQuery.access( this, fn=jQuery.attr, name, value, chainable=true);
    }

access調用簡化:

var access = function( this, jQuery.attr, name, value, chainable=true, emptyGet=undefined, raw=undefined ) {
    var i = 0,
        length = this.length, //jQuery對象的length屬性,表示找到的匹配的DOM元素的個數
        bulk = false;


        chainable = true;

        if ( !jQuery.isFunction( value ) ) { //當value值不爲函數時,設置raw爲true,這是爲了下一步if(jQuery.attr)中的raw判斷作鋪墊
            raw = true; 
        }

        
        if ( jQuery.attr ) { //jQuery.attr,爲true

            for ( ; i < length; i++ ) {  //用for循環是由於此時的this是一個包含多個DOM元素的jQuery對象
                jQuery.attr(
                    this[ i ],
                    name,
                    raw ? value : value.call( elems[ i ], i, jQuery.attr( this[ i ], name ) )                       
                );//raw爲true,也就是value不爲函數時,用value做第三參數
            }     
        }
    }

    return this; //返回jQuery對象自己

};

而,咱們用簡化的方法分析此種狀況下的jQuery.attr(this,name,value):

attr: function( this[i], name, value ) {
    var ret, hooks,
        nType = this[i].nodeType;

    if ( value !== undefined ) {  //判斷爲true,進入if語句
        if ( value === null ) {
            jQuery.removeAttr( this[i], name );//若是value爲null,刪除該jQuery對象的全部匹配元素的指定屬性
            return;
        }

        this[i].setAttribute( name, value + "" );//設置當前DOM元素的指定屬性的屬性值
        return value;
    }

    ret = jQuery.find.attr( this[i], name ); //刪除了屬性,返回null;不然,返回指定屬性的屬性值

    return ret == null ? undefined : ret; //若是刪除了指定屬性,返回undefined;若是修改了屬性,返回指定屬性值
}

調用形式:$("xxx").attr(attrObject);

attr定義:

attr: function( name=attrObject ) {
        return jQuery.access( this, jQuery.attr, name=attrObject, value=undefined, false);
    }

access調用簡化:

var access = function( this, fn, name, value=undefined, chainable=false, emptyGet=undefined, raw=undefined ) {
    var i = 0,
        length = this.length, //元素的length屬性
        bulk = false;

    // 設置多個value值
    if ( jQuery.type( name ) === "object" ) { //若是傳入的name形參爲對象類型
        chainable = true;
        for ( i in name ) { //對每個對象中的屬性名及屬性值再次調用自己(遞歸)
            access( this, fn, i, name[ i ], true, emptyGet, raw );
        }

    }
    return elems;  //返回jQuery對象自己

};

可見,對於一個由"屬性-屬性值"鍵值對構成的對象,會對其中的每個屬性都調用access設置一次.因爲代碼中使用的for-in循環,因此enumerable爲false的鍵值對是無效的.


調用形式:$("xxx").attr(name,attrFn);

attr定義:

attr: function( name, value=attrFn ) {
        return jQuery.access( this, jQuery.attr, name, value=attrFn, chainable=true );
    }

access調用簡化:

var access = function( this, jQuery.attr, name, value=attrFn, chainable=true, emptyGet=undefined, raw=undefined ) {
    var i = 0,
        length = this.length, //jQuery對象的length屬性
        bulk = false;

        chainable = true;

        if ( jQuery.attr ) {  //true,進入if語句
            for ( ; i < length; i++ ) {
                jQuery.attr(
                    this[ i ],
                    name,
                    attrFn.call( this[ i ], i, jQuery.attr( this[ i ], name ) )  // 調用attrFn,其返回值做爲第三個參數                                             
                );
            }
        }

    return elems; // 返回jQuery對象自己
};

attrFn.call( this[ i ], i, jQuery.attr( this[ i ], name ) )可知,attrFn的參數限制就是源自這一行代碼:(this[i]是調用attrFn的元素,後面兩個是參數,一個是jQuery對象中的索引值,一個是當前元素的指定屬性name的值的查詢返回)

[特別注意:attrFn的兩個參數雖然有規定,可是不須要咱們真的傳參,而是函數體內部使用索引值或者當前屬性值的一個接口]

相關文章
相關標籤/搜索