天天看點

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結構

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

分别會取得什麼值?

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

attribute和property的差別

attribute:特性

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

property:屬性

通過“.”号來進行設定、讀取的屬性,就跟Javascript裡普通對象屬性的讀取差不多

觀察一張圖很直覺的了解:

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

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各個子產品調用的複雜性

看看源碼的實作

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

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

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

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

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

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

大概意思如下:

jQuery提供一個API來調用使用者自定義的函數,用于擴充,以便擷取和設定特定屬性值

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

<code>鈎子都有相似的結構</code>

<a></a>

如何使用?

在做css3屬性浏覽器相容的時候,都需要特定的字首

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

Firefox:-moz-border-radius

此時我看可以采用一個CSS hook 可以标準化這些供應商字首的屬性,讓<code>.css()</code> 接受一個單一的,标準的屬性的名稱(<code>border-radius</code>,或用DOM屬性的文法,<code>borderRadius</code>)

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

給某一進制素設定borderRadius,為10px

為了做浏覽器相容,我們不得不

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

borderRadius = styleSupport( "borderRadius" ); //擷取到相對應的浏覽器标準

這裡可能還不直覺的展現,我們深入到attr源碼中看看

jQuery.attr 靜态方法

jQuery執行個體的方法都是調用最終的靜态方法:jQuery.attr

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

檢視源碼關于attrHooks一個type

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

省略部分代碼attr源碼

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

通過hooks = jQuery.attrHooks[ name ]方法,去适配對應的name,是否在合集中

如果是hooks然後又是get方法就調用 hooks &amp;&amp; "set" in hooks &amp;&amp; (ret = hooks.set( elem, value, name )

如果有ret傳回值就return(hooks.set可能還不是最終比對)

否則繼續往下走

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

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

那麼,利用鈎子處理相容與擴充的好處:

擴充卡這種模式對于擴充新功能非常有利

如果采用鈎子處理的話,我們就省去了一大堆if else的分支判斷

由于JS用對象做為表進行查找是比if條句與switch語句快很多

 本文轉自艾倫 Aaron部落格園部落格,原文連結:http://www.cnblogs.com/aaronjs/p/3387906.html,如需轉載請自行聯系原作者

繼續閱讀