解密jQuery核心 樣式操作
基礎回顧
jQuery裡節點樣式讀取以及設定都是通過.css()這個方法來實現的,本章通一下分解探究下jquery裡這部分程式碼的實現
那麼jQuery要處理樣式的哪些問題?
先簡單回顧下樣式操作會遇到的問題
HTML樣式定義3種方式了
<link/> 外部引入也就是定義CSS中的 <style/>嵌入式樣式 style特性地定義
給一個HTML元素設定css屬性,如
var head= document.getElementById("head"); head.style.width = "20px"; head.style.height= "10px"; head.style.display = "block";
這是DOM2級樣式提供的API了,這裡總的來說還涉及了3個問題,當然也是jQuery內部需要解決的相容問題了
1 單一的設定太麻煩,而且每次style一次就等於瀏覽器要繪製一次,當然高階的瀏覽器是可能會合並style的次數的
2 style只能針對行類樣式,對於link引入的樣式,無法獲取
3 樣式屬性名的相容問題,比如駝峰,保留字
樣式規則
任何支援style特性的HTML元素在js中有一個物件的style屬性,其實也是一個例項,但是內部屬性命名都是採用的駝峰形式的
比如 background-image =>要寫成 backgroundImage
其中一個是比較特殊的就是 float, 保留字嘛所以就換成 cssFloat, IE : styleFloat
然後對於width,hight這些處理都最好要有一個量度單位
合併cssText
可能針對一種情況給出的處理就是cssText合併
var head= document.getElementById("head"); head.style.cssText="width:20px;height:10px;display:bolck";
和innerHTML一樣,cssText很快捷且所有瀏覽器都支援。此外當批量操作樣式時,cssText只需一次reflow,提高了頁面渲染效能
當然如果是在建立的時候,我們還可以利用文件碎片
缺點自然就是樣式被整體覆蓋了,所以在處理的時候應該要先獲取需要保留的樣式然後再拼接起來
樣式訪問
之前說過了style只能獲取行類樣式了,那麼CSS外部樣式表定義的樣式如何處理?
DOM2增加了 document.defauleView,提供了 getComputedStyle()方法 返回了類似style屬性的 css的dom隱射的例項物件
自然包行了樣式表的最終樣式了
getComputedStyle與style的區別
區別就在於getComputedStyle是隻能讀的,style是可以可讀可寫的
看看jQuery的
function getStyles( elem ) { return window.getComputedStyle( elem, null ); }
沒有defauleView字首,查了下在瀏覽器中,該屬性返回當前 document
物件所關聯的 物件,如果沒有,會返回 null
。
應該就能直接window呼叫了
當然啦,IE這個老大反正就不怎麼守規矩了,getComputedStyle
方法IE6~8是不支援,所以自己弄出來了currentStyle
處理類似style的處理了,jQuery2X 可以無視IE9以下的相容了, 所以這個略過~
以上就是樣式操作需要了解是基礎了,那麼總的來說
jQuery需要的處理問題就顯而易見了
1 引數傳遞
2 命名規範
3 訪問規則
4 效能優化
.css()
關於css的介面
jQuery.fn.css 與 jQuery.css
我們知道例項是呼叫靜態的方法
css的介面引數傳遞是可以很多個組合情況的,這也符合了jQuery少寫多做的原則了
最終方法與設定樣式的方法是例項方法,所以我們看傳遞的引數就知道了,只能是單一的elem, name, value 實參
jQuery.style( elem, name, value ) :
jQuery.css( elem, name );
所以如果我們傳遞是物件或者別的方式就需要一個過濾的環節
css引數的處理也跟之前的attr屬性的處理保持一致,採用了jQuery.access方法統一調配
這個具體之前就分析了,無非就是遞迴引數,但是有個可學的設計思路
分離不同的邏輯判斷通過回撥傳遞進去
取值jQuery.css()
先看看原始碼
css: function( elem, name, extra, styles ) { var val, num, hooks, origName = jQuery.camelCase( name ); name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) ); hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; if ( hooks && "get" in hooks ) { val = hooks.get( elem, true, extra ); } if ( val === undefined ) { val = curCSS( elem, name, styles ); } if ( val === "normal" && name in cssNormalTransform ) { val = cssNormalTransform[ name ]; } if ( extra === "" || extra ) { num = parseFloat( val ); return extra === true || jQuery.isNumeric( num ) ? num || 0 : val; } return val; }
首先自然是檢測是是否駝峰寫法了,如果不是就得轉化下
origName = jQuery.camelCase( name );
把正則拖出來
'background-image'.replace(/-([\da-z])/gi, fcamelCase = function( all, letter ) { return letter.toUpperCase(); })
找到-後面的,轉成大寫開頭
修正命名float
jQuery.cssProps
css樣式的鉤子處理,針對不同的相容增加的解耦處理,這裡先跳過下章再將,不影響程式碼流程
所以最終在預設情況下是通過curCSS處理的取值
curCSS = function( elem, name, _computed ) { var width, minWidth, maxWidth, computed = _computed || getStyles( elem ), // Support: IE9 // getPropertyValue is only needed for .css('filter') in IE9, see #12537 ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined, style = elem.style;
最終就是通過getComputedStyle的getPropertyValue方法了,所以通體來說跟之前假設的處理是保持一致的,只是做了不同的相容
設值jQuery.style()
處理的方式與css類似,只是要注意了style才具有樣式的修改許可權
這樣的傳物件其實都是需要呼叫多次style處理的,當然沒有采用cssText的方式處理,因為本身以前的屬性就會丟失了
var color = a.css({"background-color":'red','width':'200px'});
總結:
jQuery的處理流程:
1. 分解引數
2. 轉換為駝峰式,修正屬性名
3. 如果有鉤子,則呼叫鉤子的set get
4. 最終實現都是依靠瀏覽器自己的API的