溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

[置頂]       jQuery亂談(五)

發(fā)布時間:2020-07-24 10:33:23 來源:網(wǎng)絡(luò) 閱讀:269 作者:873582595 欄目:web開發(fā)

今天主要分析一下jQuery設(shè)置元素DOM屬性的相關(guān)方法的具體實現(xiàn):addClass()、attr()、hasClass()、html()、prop()、removeAttr()。

  首先是addClass():

// 該方法用于向元素添加新類名 addClass: function( value ) {         var classNames, i, l, elem,             setClass, c, cl;               // 如果參數(shù)是函數(shù)的話,執(zhí)行該分支語句         if ( jQuery.isFunction( value ) ) {              // each方法在jQuery中經(jīng)常用到,因為我們操作的jQuery對象經(jīng)常是多個,該方法可以讓每個jQuery對象都執(zhí)行相應(yīng)的操作             return this.each(function( j ) {                   /* 這里用到了Function.call(),這也是在jQuery內(nèi)部實現(xiàn)中經(jīng)常用到的
還有與之類似的Function.apply()。二者都是用于改變運行上下文,
借用已存在的方法進行操作,不同點就是傳遞參數(shù)的方式
          */                 jQuery( this ).addClass( value.call(this, j, this.className) );              });         }         // 如果參數(shù)是字符串的話,執(zhí)行該分支語句         if ( value && typeof value === "string" ) {             // core_rspace = /\s+/,用于匹配一個及以上的空白字符             classNames = value.split( core_rspace ); // 將提供的參數(shù)按空白字符分開放到一個數(shù)組里              for ( i = 0, l = this.length; i < l; i++ ) {                 elem = this[ i ];                 // 確保元素是元素節(jié)點                 if ( elem.nodeType === 1 ) {                     // 如果元素的class類名不存在而且新添加的類名只有一個                     if ( !elem.className && classNames.length === 1 ) {                         elem.className = value; // 直接將參數(shù)賦值給class屬性                      } else {                         // 在元素原有的class類名字符串前后添加空白字符可以保證添加新的類名后和原來的類名不會連到一塊,從而導致錯誤                         setClass = " " + elem.className + " ";                           for ( c = 0, cl = classNames.length; c < cl; c++ ) {                             // 確保新添加的className在原來的元素的class屬性中不存在                             if ( setClass.indexOf( " " + classNames[ c ] + " " ) < 0 ) {                                 setClass += classNames[ c ] + " ";// 加“ ”可以保證類名不會連接到一塊                             }                         }                         // jQuery.trim方法用于去除字符串前后空格                         elem.className = jQuery.trim( setClass );                     }                 }             }         }          // 形成鏈式調(diào)用         return this;     }

  該方法為每個匹配的元素添加指定的類名,共有兩種使用方法:

  • addClass( className )

className為每個匹配元素所要增加的一個或多個樣式名。

  • addClass(function(index, currentClass))

function(index, currentClass)這個函數(shù)返回一個或更多用空格隔開的要增加的樣式名。接收元素的索引位置index和元素舊的樣式名currentClass作為參數(shù)。

  在該方法里有一個易錯點,就是訪問元素的class屬性不可用elem.class,因為class是ECMAScript規(guī)范中的保留字,在將來可能會在語言規(guī)范中用到,所以需要用elem.className。與之相似的是訪問元素style屬性的float屬性,需要用elem.style.cssFloat和elem.style.styleFloat,還有for屬性,應(yīng)該用htmlFor。

 

  attr()方法:

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

  怎么樣,看著簡單吧?該方法的作用就是取得第一個匹配元素的屬性值或者為指定元素設(shè)置一個或多個屬性。但是將該方法可以衍生出許多高級用法。不過我們一般就是用于直接設(shè)置和獲取屬性值。與之類似的還有prop()方法和html()方法:

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

  

html: function( value ) {         return jQuery.access( this, function( value ) {             var elem = this[0] || {},                 i = 0,                 l = this.length;              if ( value === undefined ) {                 return elem.nodeType === 1 ?                     elem.innerHTML.replace( rinlinejQuery, "" ) :                     undefined;             }              // See if we can take a shortcut and just use innerHTML             if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&                 ( jQuery.support.htmlSerialize || !rnoshimcache.test( value )  ) &&                 ( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&                 !wrapMap[ ( rtagName.exec( value ) || ["", ""] )[1].toLowerCase() ] ) {                  value = value.replace( rxhtmlTag, "<$1></$2>" );                  try {                     for (; i < l; i++ ) {                         // Remove element nodes and prevent memory leaks                         elem = this[i] || {};                         if ( elem.nodeType === 1 ) {                             jQuery.cleanData( elem.getElementsByTagName( "*" ) );                             elem.innerHTML = value;                         }                     }                      elem = 0;                  // If using innerHTML throws an exception, use the fallback method                 } catch(e) {}             }              if ( elem ) {                 this.empty().append( value );             }         }, null, value, arguments.length );     }

  prop方法一般用于獲取在匹配的元素集中的第一個元素的屬性值。高級用法是設(shè)置為匹配的元素設(shè)置一個或更多的屬性。

  html方法用于從匹配的第一個元素中獲取或設(shè)置HTML內(nèi)容。

這三個方法都用到了jQuery.access方法:

[置頂]          jQuery亂談(五)View Code

  該方法當設(shè)置/獲取屬性的時候遍歷jQuery對象,依次調(diào)用fn函數(shù)。這里的fn可能是jQuery.attr和jQuery.prop。需要注意的是這里用for遍歷elems,這個elems實際是jQuery對象,jQuery對象它是一個ArrayLike。大概就是如此,剩下的一堆hooks是用來解決瀏覽器兼容性的問題。如jQuery.attrHooks、jQuery.propHooks、jQuery.valHooks。列舉如下

  • IE6/7不完全支持setAttribute,比如不能設(shè)置class,for等屬性
  • IE6/7中g(shù)etAttribute獲取href / src 屬性(相對路徑)值與其它瀏覽器不同
  • IE6/7中獲取Button元素的值有bug
  • IE6/7不支持setAttribute設(shè)置style / 不支持getAttribute獲取style屬性值
  • 獲取tabIndex屬性有差異
  • 布爾類型屬性的修復(fù),如selected,disabled,checked等
  • select和option元素的值修復(fù)

  也許以后我會專門寫篇博客來分析這個方法。它是一個多功能的方法,用于獲取和設(shè)置集合中的值,我們只要知道這一點就行了。

  

  hasClass():

hasClass: function( selector ) {         var className = " " + selector + " ",             i = 0,             l = this.length;         for ( ; i < l; i++ ) {             if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {                 return true;             }         }          return false;     }

  該方法用于檢查匹配的元素是否含有某個特定的類selector。將參數(shù)selector轉(zhuǎn)換為" " + selector + " "是為了防止如果元素的class屬性中如果出現(xiàn)“sub selector-sup”的情況,這時如果直接用selector匹配的話,因為“selector-sup”的出現(xiàn)就會導致匹配正確,但實際上元素的class屬性中并沒有selector類名,只不過class屬性字符串中存在該字符串,從而導致錯誤。在參數(shù)前后添加空格后可以避免這個錯誤,但同時我們知道在元素的class屬性中,前后兩個類名的前/后面是沒有空格的,所以我們需要把className經(jīng)過" " + this[i].className + " "處理。l = this.length;用于緩存操作的jQuery對象集合的長度,這種方式使我們在寫JavaScript中應(yīng)該存在的意識,尤其是在DOM操作中。for循環(huán)是為了讓元素集合中的每一項都執(zhí)行該操作,在這里就是每個都檢查一下是否存在selector類名,如果其中有一項不符合,則整個不匹配。在for循環(huán)中,this[i].nodeType === 1可以保證我們將要操作的節(jié)點是元素節(jié)點,而不是文本節(jié)點等其他節(jié)點,jQuery這種安全保障機制是值得我們學習的。replace(rclass, " ")中的rclass = /[\t\r\n]/g,是把class屬性中的制表符、回車符、換行符替換成空格,形成統(tǒng)一的“ class1 class2 class3 class4 class5 ”效果,然后再indexOf檢索特定的className是否存在。這還是一種安全保障機制,jQuery真是步步為營!

 

  removeAttr()方法:

removeAttr: function( name ) {         return this.each(function() {             jQuery.removeAttr( this, name );         });     }

  該方法只接受一個參數(shù),為匹配的元素集合中的每個元素中移除一個name屬性。這里用到了jQuery.removeAttr():

/* 這里用到了propFix: {         tabindex: "tabIndex",         readonly: "readOnly",         "for": "htmlFor",         "class": "className",         maxlength: "maxLength",         cellspacing: "cellSpacing",         cellpadding: "cellPadding",         rowspan: "rowSpan",         colspan: "colSpan",         usemap: "useMap",         frameborder: "frameBorder",         contenteditable: "contentEditable"     },它用于修正IE瀏覽器中的IE6、7getAttribute、setAttribute、removeAttribute等方法的不足 */ removeAttr: function( elem, value ) {         var propName, attrNames, name, isBool,             i = 0;         // 確保要移除的屬性存在,并且節(jié)點是元素節(jié)點         if ( value && elem.nodeType === 1 ) {              // 將參數(shù)value按空格分解成數(shù)組             attrNames = value.split( core_rspace );              // 對要移除的屬性數(shù)組一個一個移除             for ( ; i < attrNames.length; i++ ) {                 name = attrNames[ i ];                  if ( name ) { // 確保要移除的屬性存在非空                     propName = jQuery.propFix[ name ] || name; // 修正IE部分瀏覽器獲取屬性的錯誤                     // rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i                     isBool = rboolean.test( name ); // 檢查要設(shè)置的屬性是否是boolean值控制的                      // 直接對非boolean值控制的屬性進行賦空值,也就是移除                     if ( !isBool ) {                          jQuery.attr( elem, name, "" );                     }                     // div = document.createElement("div");  getSetAttribute: div.className !== "t"檢查是否支持setAttribute,主要針對IE6/7                     elem.removeAttribute( getSetAttribute ? name : propName );                      // 如果該屬性由boolean值控制,并且修正后的屬性是元素的屬性,雙重保險                     if ( isBool && propName in elem ) {                         elem[ propName ] = false;                     }                 }             }         }     }

  明天繼續(xù)分析removeClass()、removeProp()、toggleClass()、val()。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI