jQuery的屬性操做模塊總共有4個部分,本篇說一下第1個部分:HTML特性部分,html特性部分是對原生方法getAttribute()和setAttribute()的封裝,用於修改DOM元素的特性的css
jQuery的靜態方法含有以下API:html
·$.attr(elem,name,null) ;若是value爲null則調用jQuery.removeAttr(elem, name)刪除該屬性
·$.attr(elem,name,value) ;設置elem元素的name屬性值爲value。
·$.attr(elem,name) ;獲取elem元素的name屬性node
jQuery/$ 實例方法(能夠經過jQuery實例調用的):jquery
·attr(obj) ;參數1是對象時 ;access()函數中驗證 表示一次性設置多個屬性
·attr(name,value) ;爲每一個匹配元素設置一個HTML屬性 ;value能夠是一個函數,取值爲返回值,也能夠爲null時表示刪除該屬性
·attr(name,NULL) ;參數2爲NULL時表示刪除全部匹配元素的name特性,間接調用removeAttr()
·attr(name) ;參數1是字符串時,參數2未指定或者設置爲false ;表示獲取第一個匹配元素的HTML屬性值。數組
舉個栗子:瀏覽器
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <script src="http://libs.baidu.com/jquery/1.7.1/jquery.min.js"></script> </head> <body> <a>連接</a> <button>淘寶</button> <!--點擊後a標籤將導航到淘寶--> <button>百度</button> <!--點擊後a標籤將導航到百度--> <button>移除</button> <!--點擊後a標籤將取消導航--> <script> let a = document.getElementsByTagName('a')[0], //獲取a標籤的引用 b1 = document.getElementsByTagName('button')[0], //淘寶按鈕的引用 b2 = document.getElementsByTagName('button')[1], //百度按鈕的引用 b3 = document.getElementsByTagName('button')[2]; //移除按鈕的引用 b1.addEventListener('click',function(){ $.attr(a,'href','http://www.taobao.com'); //經過jQuery的靜態方法設置href屬性 }) b2.addEventListener('click',function(){ $('a').attr('href','http://www.baidu.com') //經過jQuery的實例方法設置href屬性 }) b3.addEventListener('click',function(){ $("a").removeAttr('href') //移除href屬性 }) </script> </body> </html>
渲染的頁面以下:app
此時對應的DOM結構以下:函數
當咱們點擊淘寶按鈕後頁面變爲了以下:工具
DOM修改了這樣子:源碼分析
此時點擊這個a標籤將連接到淘寶網,而後咱們點擊百度,連接會連接到百度去的,最後點擊移除時,該a標籤又會變爲初始化的狀態。這就是jQuery的html特性操做
源碼分析
$.attr和$.removeAttr實現以下:
jQuery.extend({ attr: function( elem, name, value, pass ) { //設置或讀取html屬性,是對原生方法getAttribute()和setAttribute()的簡化 var ret, hooks, notxml, nType = elem.nodeType; // don't get/set attributes on text, comment and attribute nodes if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { //若是elem爲空 或者是文本、註釋、屬性節點 return; //直接返回,不接着處理 } if ( pass && name in jQuery.attrFn ) { return jQuery( elem )[ name ]( value ); } // Fallback to prop when attributes are not supported if ( typeof elem.getAttribute === "undefined" ) { //若是不支持方法getAttribute return jQuery.prop( elem, name, value ); //則調用對應的DOM屬性 } notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); //判斷elem是否不是xml文檔元素 // All attributes are lowercase // Grab necessary hook if one is defined if ( notxml ) { name = name.toLowerCase(); hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook ); } if ( value !== undefined ) { //若是傳入了參數value,表示是設置值 if ( value === null ) { //若值是null,則移除該name屬性 jQuery.removeAttr( elem, name ); return; } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) { //優先調用對應的修正對象的修正方法set() return ret; } else { elem.setAttribute( name, "" + value ); //不然調用原生方法setAttribute()設置html屬性 return value; } } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) { //若是未傳入參數value,優先調用對應的修正對象的修正方法get() return ret; } else { ret = elem.getAttribute( name ); //不然調用原生方法getAttrubute()讀取html屬性。 // Non-existent attributes return null, we normalize to undefined return ret === null ? undefined : ret; } }, removeAttr: function( elem, value ) { //從DOM元素上移除一個或多個html屬性,多個html屬性用空格分隔。是對removeAttribute的封裝和擴展。 var propName, attrNames, name, l, i = 0; if ( value && elem.nodeType === 1 ) { //若是設置了value參數 且 elem是一個元素節點 attrNames = value.toLowerCase().split( rspace ); //執行後attrNames是一個數組,保存了要移除的屬性名:好比:Array [ "id", "name" ] rspace = /\s+/, l = attrNames.length; //須要移除的屬性的個數 for ( ; i < l; i++ ) { //遍歷數組attrNames,逐個移除html屬性。 name = attrNames[ i ]; //name是要移除的屬性名 if ( name ) { propName = jQuery.propFix[ name ] || name; //若是屬性名name須要修正,則修正屬性 // See #9699 for explanation of this approach (setting first, then removal) jQuery.attr( elem, name, "" ); //先將html屬性設置爲空字符串,以解決Webkit內核瀏覽器不能 elem.removeAttribute( getSetAttribute ? name : propName ); //調用原生方法removeAttribute刪除對應的屬性,若是jQuery.support.getSetAttribute爲true則刪除name屬性,若是爲false,表示在IE六、7下則刪除特殊屬性。 // Set corresponding property to false for boolean attributes if ( rboolean.test( name ) && propName in elem ) { //對應布爾屬性,同步設置對應的DOM屬性爲false elem[ propName ] = false; } } } } }, /**/ })
對於jQuery實例來講,它調用了不一樣的工具函數,最後仍是執行上面講解的靜態方法的,以下:
jQuery.fn.extend({ attr: function( name, value ) { //移除、設置html屬性 return jQuery.access( this, name, value, true, jQuery.attr ); //調用了jQuery.access工具函數,參數5傳入了jQuery.attr }, removeAttr: function( name ) { //移除html屬性 return this.each(function() { //經過each函數方法,依次執行jQuery.removeAttr() jQuery.removeAttr( this, name ); }); }, /*略*/ })
因爲jQuery中的特性、DOM屬性和樣式操做的函數參數能夠是差很少的,jQuery就定義了一個access函數,爲.attr()、.prop()、.css()提供支持,這樣咱們經過jQuery實例設置特性、屬性和樣式時能夠傳入的參數類型,例如:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <script src="http://libs.baidu.com/jquery/1.7.1/jquery.min.js"></script> </head> <body> <a>連接</a> <script> $('a').attr('href','http://www.cnblogs.com') //參數2是個字符串 $('a').attr('href',()=>'http://www.cnblogs.com') //參數2仍是是個函數 $('a').attr({href:'http://www.cnblogs.com'}) //也能夠傳入一個對象 </script> </body> </html>
咱們傳入不一樣的參數,均可以實現設置特性的效果,這就是$.access的做用,$.access的源碼實現以下:
jQuery.extend({ access: function( elems, key, value, exec, fn, pass ) { //爲集合中的元素設置一個或多個屬性值,或者讀取第一個元素的屬性值 var length = elems.length; // Setting many attributes if ( typeof key === "object" ) { //若是key是對象,表示要設置多個屬性,則遍歷該對象循環執行.access函數 for ( var k in key ) { jQuery.access( elems, k, key[k], exec, fn, value ); } return elems; } // Setting one attributes if ( value !== undefined ) { //若是參數value不是undefined,表示要設置單個屬性 // Optionally, function values get executed if exec is true exec = !pass && exec && jQuery.isFunction(value); //修正exec參數。若是沒有傳入pass參數或者該參數值是false,且參數exec爲true,且value是函數則設置exec爲true,不然exec爲false。 for ( var i = 0; i < length; i++ ) { fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); //遍歷元素集合elems,爲每一個元素調用回調函數fn } return elems; //遍歷完成後返回元素elems。以支持鏈式操做 } // Getting an attribute return length ? fn( elems[0], key ) : undefined; //當value參數爲空,且元素集合elems不爲空則獲取第一個匹配元素相關的信息,即執行fn函數 }, /**/ })
writer by:大沙漠 QQ:22969969
以後的DOM屬性和樣式操做都會借用access這個工具方法的。