jQuery 2.0.3 源碼分析 鈎子機制 - 屬性操作


jQuery提供了一些快捷函數來對dom對象的屬性進行存取操作. 這一部分還是比較簡單的.

根據API這章主要是分解5個方法

  • .attr()   獲取匹配的元素集合中的第一個元素的屬性的值  或 設置每一個匹配元素的一個或多個屬性。
  • .prop() 獲取匹配的元素集中第一個元素的屬性(property)值或設置每一個匹配元素的一個或多個屬性。
  • .removeAttr() 為匹配的元素集合中的每個元素中移除一個屬性(attribute)。
  • .removeProp() 為集合中匹配的元素刪除一個屬性(property)。
  • .val() 獲取匹配的元素集合中第一個元素的當前值或設置匹配的元素集合中每個元素的值

 

jQuery的主要工作還是為了解決瀏覽器的兼容性. 這部分的方法一般都有2個特點.

  • set方法和get方法一體化. 根據參數數量來判斷是set還是get.
  • value可以傳入一個閉包. 這個閉包的返回值才是真正的value.

 


先看一組HTML結構

<input id="Aaron" type="checkbox" checked="checked" />

用attr,與prop取值出input元素上的checked

分別會取得什么值?

$('input').attr('checked')  //checked 

$('input').prop('checked')  // true

看到這里應該知道這兩個方法的區別了。其實從方法名也可以大致猜出來,.attr()、.prop()分別取的是節點的attribute值、property值。

 


attribute和property的區別

attribute:特性

  • 直接寫在標簽上的屬性,可以通過setAttribute、getAttribute進行設置、讀取

property:屬性

  • 通過“.”號來進行設置、讀取的屬性,就跟Javascript里普通對象屬性的讀取差不多

 

觀察一張圖很直觀的理解:

image

attributes是一個類數組的容器,說得准確點就是NameNodeMap,總之就是一個類似數組但又和數組不太一樣的容器。attributes的每個數字索引以名值對(name=”value”)的形式存放了一個attribute節點。

attributes是會隨着添加或刪除attribute節點動態更新的。

特性的操作:

  • getAttribute
  • setAttribute
  • removeAttribute

property就是一個屬性,如果把DOM元素看成是一個普通的Object對象,那么property就是一個以名值對(name=”value”)的形式存放在Object中的屬性。要添加和刪除property也簡單多了,和普通的對象沒啥分別。

之所以attribute和property容易混倄在一起的原因是,很多attribute節點還有一個相對應的property屬性

DOM元素一些默認常見的attribute節點都有與之對應的property屬性,比較特殊的是一些值為Boolean類型的property,如一些表單元素。

總的來說:基本可以總結為attribute節點都是在HTML代碼中可見的,而property只是一個普通的名值對屬性

 


  • jQuery.prototype.attr
  • jQuery.prototype.prop
  • jQuery.prototype.removeAttr
  • jQuery.prototype.removeProp
  • jQuery.prototype.val

jQuery把又長又難記的函數用外觀模式包裝成attr,prop,內部setAttribute,getAttribute是低級API,實現核心功能, 從而隱藏了用戶程序對jQuery各個模塊調用的復雜性

看看源碼的實現

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

暴露給api的原型方法非常簡單,只有一句話.把參數交給jQuery.access函數去處理. jQuery.access主要作用是修正參數.

access函數里的第二個參數jQuery.attr. 這個參數的作用是告訴access方法, 修正完參數后再去調用 jQuery.attr方法.

access方法是可以被抽象出復用的一組對參數的修正方法,通過分解成單一的數據后,然后調用傳遞的回調處理鈎子 比如 attr,css, prop.等等

 

jQuery.access源碼

access源碼部分比較簡單, 就是對象傳參分解成單一的參數從而set,get處理

 


關於jQuery Hooks 

你知道一些核心jQuery函數都有自己的“插件API”稱為“鈎子”?

詳見:http://blog.rodneyrehm.de/archives/11-jQuery-Hooks.html

大概意思如下:

jQuery提供一個API來調用用戶自定義的函數,用於擴展,以便獲取和設置特定屬性值

主要是:.attr(), .prop(), .val() and .css()四種類型的處理

鈎子都有相似的結構

var someHook = {
    get: function(elem) {
        // obtain and return a value
        return "something";
    },
    set: function(elem, value) {
        // do something with value
    }
}

 

 


如何使用?

用jQuery官方提供的為列 http://www.css88.com/jqapi-1.9/jQuery.cssHooks/

在做css3屬性瀏覽器兼容的時候,都需要特定的前綴

Webkit的瀏覽器:-webkit-border-radius

Firefox:-moz-border-radius

此時我看可以采用一個CSS hook 可以標准化這些供應商前綴的屬性,讓.css() 接受一個單一的,標准的屬性的名稱(border-radius,或用DOM屬性的語法,borderRadius

判斷的代碼省略,直接看實現

給某一元素設置borderRadius,為10px

$("#element").css("borderRadius", "10px");

為了做瀏覽器兼容,我們不得不

if(webkit){
   ........................
}else if(firefox){
  ............................
}else if(...)更多

這是一種最沒技術含量的寫法了,如果我們換成一種hook的話

$.cssHooks.borderRadius = {
      get: function( elem, computed, extra ) {
        return $.css( elem, borderRadius );
      },
      set: function( elem, value) {
        elem.style[ borderRadius ] = value;
      }
    };

borderRadius = styleSupport( "borderRadius" ); //獲取到相對應的瀏覽器標准

這里可能還不直觀的體現,我們深入到attr源碼中看看

 


jQuery.attr 靜態方法

jQuery實例的方法都是調用最終的靜態方法:jQuery.attr

access函數最后把參數又傳遞給了jQuery.attr, 在jQuery.attr里才真正進行setAttribute/getAttribute操作.

 

查看源碼關於attrHooks一個type

意思就是在使用attr(‘type’,??)設置的時候就會調用這個hooks,用於處理IE6-9 input屬性不可寫入的問題

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 creation
                        var val = elem.value;
                        elem.setAttribute( "type", value );
                        if ( val ) {
                            elem.value = val;
                        }
                        return value;
                    }
                }
            }
        },

 

省略部分代碼attr源碼

image

 

  • 通過hooks = jQuery.attrHooks[ name ]方法,去適配對應的name,是否在合集中
  • 如果是hooks然后又是get方法就調用 hooks && "set" in hooks && (ret = hooks.set( elem, value, name )
  • 如果有ret返回值就return(hooks.set可能還不是最終匹配)
  • 否則繼續往下走

 

其實這樣的思路,在sizzle選擇器也大量的運用了

鈎子就是適配器原理,用來處理一些特殊的屬性,樣式或事件。而這些屬性,樣式或事件,我們可以通過瀏覽器的特征嗅探,把相應的解決方法添加到適配器中。有了這些適配器,jQuery就可以省去許多if else 判定


那么,利用鈎子處理兼容與擴展的好處:

  • 適配器這種模式對於擴展新功能非常有利
  • 如果采用鈎子處理的話,我們就省去了一大堆if else的分支判斷
  • 由於JS用對象做為表進行查找是比if條句與switch語句快很多

 

本章的重點在於如何靈活運用運用鈎子的原理,在實際項目中更好的處理兼容與擴展


免責聲明!

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



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