標籤:des style blog http io ar color sp on
我們知道,$().attr()實質上是內部調用了jQuery.access方法,在調用時jQuery.attr作為回調傳入。在通過種種判斷(參看jQuery.access()方法)之後,取值和賦值最後調用了這個jQuery.attr方法。
所以,關鍵是看jQuery.attr這裡怎麼走了~~
源碼如下:
attr: function( elem, name, value ) { var hooks, ret, nType = elem.nodeType; //如果elem不存在,或者是文本、注釋、屬性節點 // don‘t get/set attributes on text, comment and attribute nodes if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { return; } // Fallback to prop when attributes are not supported if ( typeof elem.getAttribute === core_strundefined ) {//如果elem不支援getAttribute 比如document或者文檔片段 return jQuery.prop( elem, name, value );//調用jQuery.prop方法 } // All attributes are lowercase // Grab necessary hook if one is defined //? if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {//elem不是標籤或者elem不在xml中 name = name.toLowerCase();//屬性名稱大寫 hooks = jQuery.attrHooks[ name ] || ( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook );//jQuery.attrHooks.type } if ( value !== undefined ) {//賦值 if ( value === null ) {//如果設的值為null,相當於移除attr ,比如.attr(‘checked‘,null); jQuery.removeAttr( elem, name ); } else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {//調用鉤子的set方法 return ret; } else { elem.setAttribute( name, value + "" );//如果value是數值,隱式轉為字串 return value; } } else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {//調用鉤子的get return ret; } else {//取值 ret = jQuery.find.attr( elem, name );//調用Sizzle.attr 因為jquery中有一句:jQuery.find = Sizzle; //將null值修正為undefined // Non-existent attributes return null, we normalize to undefined return ret == null ? undefined : ret; } }
從上面的代碼看,有7個走向:
1、return
2、jQuery.prop
3、jQuery.removeAttr
4、attrHooks.set
5、elem.setAttribute
6、attrHooks.get
7、Sizzle.attr
前面5個都是設定值,6和7是讀值。
2和3以後會讀到,這裡不提,先看看Sizzle.attr中是怎麼一回事吧^^
Sizzle.attr = function( elem, name ) { // Set document vars if needed if ( ( elem.ownerDocument || elem ) !== document ) {//如果不是當前document setDocument( elem );//不知道幹嘛 考慮iframe的情況? } //Expr.attrHandle是一個對象,包含了 //async autofocus autoplay checked controls defer disabled hidden ismap loop //multiple open readonly required scoped selected 等自訂方法(屬性) var fn = Expr.attrHandle[ name.toLowerCase() ], // Don‘t get fooled by Object.prototype properties (jQuery #13807) //hasOwn 就是hasOwnProperty //所以這個hasOwn.call( Expr.attrHandle, name.toLowerCase() ) 是在判斷傳入的屬性名稱是不是這個對象的 //自訂屬性,而不是原型上的屬性 //val為調用自訂方法的結果或者undefined val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? fn( elem, name, !documentIsHTML ) : undefined; //如果val為undefined //如果(support.attributes為真或者document不是html),返回elem.getAttribute( name )的值 //否則 val為 elem.getAttributeNode(name))的值 //如果val為真,並且val.specified為真,返回val.value //否則返回null //否則返回val return val === undefined ? support.attributes || !documentIsHTML ? elem.getAttribute( name ) : (val = elem.getAttributeNode(name)) && val.specified ? val.value : null : val;};
複雜的三元運算子看得頭都大了有木有,好吧,這裡能看到,取值用getAttribute或者getAttributeNode。
再看attrHooks是一些什麼內容:
attrHooks: { type: { set: function( elem, value ) { if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { // Setting the type on a radio button after the value resets the value in IE6-9 // Reset value to default in case type is set after value during creationvar val = elem.value; elem.setAttribute( "type", value ); if ( val ) { elem.value = val; } return value; } } } }
從這裡可以看到,attrHooks與設定input標籤的type值有關,恩,如果設定的值為radio的時候,注意下。
jQuery.attr() 源碼解讀