分類:
版權聲明:本文為博主原創文章,未經博主允許不得轉載。
閒話
原計畫是沒有這篇博文的,研究animation源碼的時候遇到了css樣式這個攔路虎。比如jQuery支持「+=10」、「+=10px」定義一個屬性的增量,但是有的屬性設置時可以支持數字,有的必須有單位;在對屬性當前值讀取時,不同的瀏覽器可能返回不同的單位值,無法簡單的相加處理;在能否讀取高寬等位置信息上,還會受到display狀態的影響;不同瀏覽器,相同功能對應的屬性名不同,可能帶有私有前綴等等。
眾多的疑問,讓我決定先破拆掉jQuery的樣式機制。
(本文採用 1.12.0 版本進行講解,用 #number 來標註行號)
css
jQuery實現了一套簡單統一的樣式讀取與設置的機制。$(selector).css(prop)讀取,$(selector).css(prop, value)寫入,也支持對象參數、映射寫入方式。厲害的是,這種簡單高效的用法,完全不用考慮兼容性的問題,甚至包括那些需要加上前綴的CSS3屬性。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
如何統一一個具有眾多兼容問題的系統呢?jQuery的思路是抽象一個標準化的流程,然後對每一個可能存在例外的地方安放鉤子,對於需要例外的情形,只需外部定義對應的鉤子即可調整執行過程,即標準化流程 + 鉤子。
下面我們來逐個擊破!
1、access
jQuery.fn.css( name, value )
的功能是對樣式的讀取和寫入,屬於外部使用的外觀方法。內部的核心方法是jQuery.css( elem, name, extra, styles )
、jQuery.style( elem, name, value, extra )
。
jq中鏈式調用、對象寫法、映射、無value則查詢這些特點套用在了很多API上,分成兩類。比如第一類:jQuery.fn.css(name, value)、第二類:jQuery.fn.html(value),第二類不支持對象參數寫法。jq抽離了不變的邏輯,抽象成了
access( elems, fn, key, value, chainable, emptyGet, raw )
入口。
難點(怪異的第二類)
第一類(有key,bulk = false)
普通(raw):對elems(一個jq對象)每一項->fn(elems[i], key, value)
映射(!raw):對elems每一項elems[i],求得key屬性值val=fn(elems[i], key),執行map(即value)函數value.call( elems[ i ], i, val )得到返回值re,執行fn(elems[i], key, re)
取值(!value):僅取第一項fn( elems[ 0 ], key )
第一類(有key,bulk = false)
普通(raw):對elems(一個jq對象)每一項->fn(elems[i], key, value)
映射(!raw):對elems每一項elems[i],求得key屬性值val=fn(elems[i], key),執行map(即value)函數value.call( elems[ i ], i, val )得到返回值re,執行fn(elems[i], key, re)
取值(!value):僅取第一項fn( elems[ 0 ], key )
第二類(無key,bulk = true)
普通(raw):直接fn.call(elems, value)
映射(!raw):對elems每一項elems[i],求得值val=fn.call( jQuery( elems[i] )),執行map(即value)函數value.call( jQuery(elems[ i ]), val )得到返回值re,執行fn.call( jQuery( elems[i] ), re)
取值(!value):取fn.call( elems )
普通(raw):直接fn.call(elems, value)
映射(!raw):對elems每一項elems[i],求得值val=fn.call( jQuery( elems[i] )),執行map(即value)函數value.call( jQuery(elems[ i ]), val )得到返回值re,執行fn.call( jQuery( elems[i] ), re)
取值(!value):取fn.call( elems )
正是這兩類的不同造成了access內部邏輯的難懂,下面代碼中第二類進行fn封裝,就是為了bulk->!raw->map能夠與第一類使用同樣的邏輯。兩類的使用方法,包括映射參數寫法都是不同的。有value均為鏈式調用chainable=true
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
讀取依賴window上的getComputedStyle方法,IE6-8依賴元素的currentStyle方法。樣式的寫入依賴elem.style。
2、jQuery.fn.css
jQuery.fn.css( name, value )為什麼會有兩個核心方法呢?因為樣式的讀取和寫入不是同一個方式,而寫入的方式有時候也會用來讀取。
讀:依賴window上的getComputedStyle方法,IE6-8依賴元素的currentStyle方法。內聯外嵌的樣式都可查到
寫:依賴elem.style的方式。而elem.style方式也可以用來查詢的,但是只能查到內聯的樣式
寫:依賴elem.style的方式。而elem.style方式也可以用來查詢的,但是只能查到內聯的樣式
因此封裝了兩個方法
jQuery.css( elem, name, extra, styles )
、jQuery.style( elem, name, value, extra )
,前者只讀,後者可讀可寫,但是後者的讀比較雞肋,返回值可能出現各種單位,而且還無法查到外嵌樣式,因此jQuery.fn.css方法中使用前者的讀,後者的寫- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
3、屬性名兼容
第一步:jq支持駝峰和』-『串聯兩種寫法,會在核心方法中統一轉化為小駝峰形式
第二步:不同瀏覽器的不同屬性名兼容,如float為保留字,標準屬性是cssFloat,IE中使用styleFloat(當前版本IE已拋棄)。查看是否在例外目錄中
第三步:css3屬性支持程度不一,有的需要加上私有前綴才可使用。若加上私有前綴才能用,添加到例外目錄中方便下次拿取
第二步:不同瀏覽器的不同屬性名兼容,如float為保留字,標準屬性是cssFloat,IE中使用styleFloat(當前版本IE已拋棄)。查看是否在例外目錄中
第三步:css3屬性支持程度不一,有的需要加上私有前綴才可使用。若加上私有前綴才能用,添加到例外目錄中方便下次拿取
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
4、jQuery.css、jQuery.style
jq的樣式機制之所有複雜,因為在核心方法功能的設計上,考慮了非必要的「易用」、「兼容」、「擴展」。使得設置更靈活、輸出更一致、支持累加換算、支持拓展的功能。由於對下面特性的支持,因此對樣式的取值抽象出了核心邏輯
curCSS( elem, name, computed )
,一來是邏輯劃分更清晰,內部更可根據需要酌情選擇使用這兩者
易用
1、為了提高易用性,jQuery.style()可以自動為設置值加上默認單位』px',由於有些屬性值可以為數字,因此定義了
cssNumber
的列表,列表中的項目不會加上默認單位。
2、允許增量』+=20px'式寫法,由於採用jQuery.css獲取的初始值單位有可能不同,因此封裝了一個自動單位換算並輸出增量後最終結果的函數
adjustCSS()
兼容
並不是每個屬性都能返回預期的值。
1、比如opacity在IE低版本是filter,用jQuery.style方式取值時需要匹配其中數字,結果跟opacity有100倍差距,而且設置的時候alpha(opacity=num)的形式也太獨特。
2、比如定位信息會因為元素display為none等狀態無法正確獲取到getBoundingClientRect()、offsetLeft、offsetWidth等位置信息及大小,而且對於自適應寬度無法取得寬高信息。
3、比如一些瀏覽器兼容問題,導致某些元素返回百分比等非預期值。
jQuery.cssHooks
是樣式機制的鉤子系統。可以對需要hack的屬性,添加鉤子,在jQuery.css、jQuery.style讀取寫入之前,都會先看是否存在鉤子並調用,然後決定是否繼續下一步還是直接返回。通過在set
、get
屬性中定義函數,使得行為正確一致。
擴展
1、返回值:jQuery.css對樣式值的讀取,可以指定對於帶單位字符串和」auto」等字符串如何返回,新增了
extra
參數。為」「(不強制)和true(強制)返回去單位值,false不做特殊處理直接返回。
2、功能擴展:jq允許直接通過innerWidth()/innerHeight()、outerWidth()/outerHeight()讀取,也支持賦值,直接調整到正確的寬高。這是通過extra指定padding、border、margin等字符串做到的
3、cssHooks.expand:對於margin、padding、borderWidth等符合屬性,通過擴展expand接口,可以得到含有4個分屬性值的對象。
bug
使用字符串』30』和數字30的效果有區別。對於不能設為數字的,數字30自動加上px,字符串的卻不會。
下面adjustCSS換算函數中也提到一個bug,下面有描述。
使用字符串』30』和數字30的效果有區別。對於不能設為數字的,數字30自動加上px,字符串的卻不會。
下面adjustCSS換算函數中也提到一個bug,下面有描述。
建議:adjustCSS函數本身就可以處理增量和直接量兩種情況,type===』string'判斷的地方不要ret[ 1 ],以解決第一個問題。adjustCSS返回一個數組,第一個為值,第二個為單位,這樣就防止第二個bug。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
5、adjsutCSS換算
adjustCSS( elem, prop, valueParts, tween )
用於調用jQuery.style對增量計算的換算,並得到最終值。在jq內部,除了css樣式會換算,動畫處理也支持換算。這裡也可以把動畫的tween對象的初始值和增量進行累加換算,得到最終值賦給tween對象
難點:
這裡需要知道
maxIterations設為20有兩個原因:1、js浮點誤差可能導致兩邊總是不相等;2、對於首次調整單位變成了很小的倍數趨近於0無法計算,則通過重置為0.5每次乘2直到可以計算,慢慢的調整差距
這裡需要知道
jQuery.css( elem, prop, "" )
通過computedStyle/currentStyle求得的值單位不變,並且被extra=」「去掉了單位。比如初始值是30px,增量為』+=1rem',先使用增量的單位30rem,然後調用jQuery.css查詢跟修改前的初始值比較,比如變成了scale=15倍,則30rem/15=2rem求得原值換算後為2rem,然後再累加返回3rem。maxIterations設為20有兩個原因:1、js浮點誤差可能導致兩邊總是不相等;2、對於首次調整單位變成了很小的倍數趨近於0無法計算,則通過重置為0.5每次乘2直到可以計算,慢慢的調整差距
bug(建議見第4點):
cssNumber列表中屬性的值使用無單位增量如』+=10』,而初始值單位為px,將按照初始值單位』+=10px'處理後返回。但返回到外部,由於在cssNumber列表中,並不會再次加上單位,按照倍數被設置了。
比如lineHeight初始值20px,使用』+=4』,變成了賦值24倍
cssNumber列表中屬性的值使用無單位增量如』+=10』,而初始值單位為px,將按照初始值單位』+=10px'處理後返回。但返回到外部,由於在cssNumber列表中,並不會再次加上單位,按照倍數被設置了。
比如lineHeight初始值20px,使用』+=4』,變成了賦值24倍
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
6、curCSS、getStyles
curCSS( elem, name, computed )
是對getStyles( elem )
的封裝,可以通過computed指定樣式對象替代內部的getStyle。對高版本瀏覽器和低版本IE getStyle分別使用的getComputedStyle、currentStyle,前者是全局對象下的屬性,所以源碼中使用了ownerDocument.defaultView指代。
不同的瀏覽器,對屬性的返回可能出現百分比等非px返回值,jq通過鉤子處理個體,curCSS內部也處理了一些情況,比如Chrome、Safari的margin相關屬性值返回百分比,低版本IE的非top等位置屬性返回百分比等。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
7、cssHooks鉤子
正如第4點提到的,cssHooks存在的主要目的是應對存取出現的不一致行為。jq用support對象放置測試後的兼容性信息,源碼#6519 - #6690行有很多support對象的樣式方面兼容測試,內部通過
addGetHookIf( conditionFn, hookFn )
來綁定鉤子。鉤子有個computed參數,用於標記是jQuery.css/style哪個方法的讀操作觸發的,對應true/false
存:存的不一致只有一個
1、opacity透明度對於IE內部使用filter,需要設置為alpha(opacity=100*value)的形式
*、對於padding、borderWidth、height、width的存只是做了負數變為0的特殊處理。
*、對於padding、borderWidth、height、width的存只是做了負數變為0的特殊處理。
取:取的不一致比較多
1、opacity的」「按」1」處理,對於需要使用filter的IE低版本也要hook
2、height、width的獲取需要display不為none和帶有table的任意值(除了table、table-cell、table-caption三樣),因此提供了
3、marginLeft、marginRight對於不支持返回可靠值的瀏覽器做處理,marginRight在display為」inline-block」下取值,marginLeft通過getBoundingClientRect比對與marginLeft設置為0後的位置差得到
4、top、left中有可能返回百分比的瀏覽器,先取值,若不為px單位,則調用內部position方法計算top、left(但是此方法是相對有定位父集或html的,對於position為relative的是有bug的,個人建議源碼中可以對relative的使用getBoundingClientRect比對處理)
2、height、width的獲取需要display不為none和帶有table的任意值(除了table、table-cell、table-caption三樣),因此提供了
swap( elem, options, callback, args )
用於以指定屬性狀態調用函數取值,之後還原狀態3、marginLeft、marginRight對於不支持返回可靠值的瀏覽器做處理,marginRight在display為」inline-block」下取值,marginLeft通過getBoundingClientRect比對與marginLeft設置為0後的位置差得到
4、top、left中有可能返回百分比的瀏覽器,先取值,若不為px單位,則調用內部position方法計算top、left(但是此方法是相對有定位父集或html的,對於position為relative的是有bug的,個人建議源碼中可以對relative的使用getBoundingClientRect比對處理)
擴展: innerWidth()/innerHeight()/outerWidth()/outerHeight()
盒模型默認是寬高不包括padding、border、margin。css3里有boxSizing屬性,content-box|border-box|inherit分別代表 「不包括padding、border、margin」 | 「包含border和padding」 | 「繼承」。
jq通過innerWidth()/innerHeight()可以直接查詢/設置content-box區域的長寬;通過outerWidth()/outerHeight()可查詢/設置為border-box區域的長寬,增加一個參數true,如([value, ]true),可查詢/設置為border-box區域加上margin區域的總長寬。
jq仍然是設置height、width,不過它會進行換算。通過
augmentWidthOrHeight( elem, name, extra, isBorderBox, styles )
計算增量(數值),通過getWidthOrHeight( elem, name, extra )
得到最終值(帶px字符串)。通過extra
來指明按照content、padding、border、margin中哪一個級別。
注意:
cssHooks內若要得到自身屬性的樣式,不調用jQuery.css,而是直接調用curCSS,包括getWidthOrHeight內,因為curCSS是純粹的取值,不會調用鉤子造成死循環
cssHooks內若要得到自身屬性的樣式,不調用jQuery.css,而是直接調用curCSS,包括getWidthOrHeight內,因為curCSS是純粹的取值,不會調用鉤子造成死循環
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
- 217
- 218
- 219
- 220
- 221
- 222
- 223
- 224
- 225
- 226
- 227
- 228
- 229
- 230
- 231
- 232
- 233
- 234
- 235
- 236
- 237
- 238
- 239
- 240
- 241
- 242
- 243
- 244
- 245
- 246
- 247
- 248
- 249
- 250
- 251
- 252
- 253
- 254
- 255
- 256
- 257
- 258
- 259
- 260
- 261
- 262
- 263
- 264
- 265
- 266
- 267
- 268
- 269
- 270
- 271
- 272
- 273
- 274
- 275
- 276
- 277
- 278
- 279
- 280
- 281
- 282
- 283
- 284
- 285
- 286
- 287
- 288
- 289
- 290
- 291
- 292
- 293
- 294
- 295
- 296
- 297
- 298
- 299
- 300
- 301
- 302
- 303
- 304
- 305
- 306
- 307
- 308
- 309
- 310
- 311
- 312
- 313
- 314
- 315
- 316
- 317
- 318
- 319
- 320
- 321
- 322
- 323
- 324
- 325
- 326
- 327
- 328
- 329
- 330
- 331
- 332
- 333
- 334
- 335
- 336
- 337
- 338
- 339
- 340
- 341
- 342
- 343
- 344
- 345
- 346
- 347
- 348
- 349
- 350
- 351
- 352
- 353
- 354
- 355
- 356
- 357
- 358
- 359
- 360
- 361
- 362
- 363
- 364
- 365
- 366
- 367
- 368
- 369
- 370
- 371
- 372
- 373
- 374
- 375
- 376
- 377
- 378
- 379
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
- 217
- 218
- 219
- 220
- 221
- 222
- 223
- 224
- 225
- 226
- 227
- 228
- 229
- 230
- 231
- 232
- 233
- 234
- 235
- 236
- 237
- 238
- 239
- 240
- 241
- 242
- 243
- 244
- 245
- 246
- 247
- 248
- 249
- 250
- 251
- 252
- 253
- 254
- 255
- 256
- 257
- 258
- 259
- 260
- 261
- 262
- 263
- 264
- 265
- 266
- 267
- 268
- 269
- 270
- 271
- 272
- 273
- 274
- 275
- 276
- 277
- 278
- 279
- 280
- 281
- 282
- 283
- 284
- 285
- 286
- 287
- 288
- 289
- 290
- 291
- 292
- 293
- 294
- 295
- 296
- 297
- 298
- 299
- 300
- 301
- 302
- 303
- 304
- 305
- 306
- 307
- 308
- 309
- 310
- 311
- 312
- 313
- 314
- 315
- 316
- 317
- 318
- 319
- 320
- 321
- 322
- 323
- 324
- 325
- 326
- 327
- 328
- 329
- 330
- 331
- 332
- 333
- 334
- 335
- 336
- 337
- 338
- 339
- 340
- 341
- 342
- 343
- 344
- 345
- 346
- 347
- 348
- 349
- 350
- 351
- 352
- 353
- 354
- 355
- 356
- 357
- 358
- 359
- 360
- 361
- 362
- 363
- 364
- 365
- 366
- 367
- 368
- 369
- 370
- 371
- 372
- 373
- 374
- 375
- 376
- 377
- 378
- 379
8、innerWidth/Height()、outerWidth/Height()
第7點已經講了很多,增量的處理,並不在這幾個函數中,統一交給了augmentWidthOrHeight,使得邏輯變得簡單統一,很好的實踐了分離可變與不變的思想。
注意:它們不受jQuery.style中的小bug(如200有效,』200』無效)影響。它們不在cssNumber列表,雖然不會再該函數裡為字符串自動補px,但是鉤子中的setPositiveNumber是自動補單位px輸出的。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
9、display與jQuery.fn.show/hide/toggle
與jQuery.fn.css()在一起定義的還有jQuery.fn.show/hide/toggle()方法,通過display:none影響元素的可見性。如同swap函數會記錄樣式並還原一樣,為了讓隱藏還原為可見的過程中display與隱藏前保持一致,把display的原狀態存入jQuery._data(elem, 「olddisplay」)緩存,對於沒有緩存的顯示的時候會調用
defaultDisplay( nodeName )
首先查詢elemdisplay列表中是否有默認值,若沒有,內部調用actualDisplay( name, doc )
通過創建一個相同標籤檢測display得到需要設置的display值(結果會添加到elemdisplay列表加快以後查詢),從而保證正確的顯示狀態。這一切的核心過程就是showHide()
showHide()這個函數跟jq中很多函數一樣,很污!合併大量分支條件,就是不肯多寫兩行代碼的臭毛病,原諒我年輕,趕腳是在炫技!!
要點:
1、設置為hide,都是通過elem.style.display= none。緩存顯示狀態到_data(已經有緩存值則不需要)
2、當調整為顯示時使用緩存值。緩存值一定是最終可靠值,儘管信任
3、這種邏輯關係建立在只通過showHide()機制控制是否顯示,這樣記憶的值才能真正代表上一次
1、設置為hide,都是通過elem.style.display= none。緩存顯示狀態到_data(已經有緩存值則不需要)
2、當調整為顯示時使用緩存值。緩存值一定是最終可靠值,儘管信任
3、這種邏輯關係建立在只通過showHide()機制控制是否顯示,這樣記憶的值才能真正代表上一次
show 變量代表變為顯示狀態,hidden 變量代表本身是隱藏
show(設置顯示) -> hidden(本身隱藏) :調整為_data緩存中保存的用於顯示的設置;若無緩存,先把display設置為」「,若此時檢測仍為hidden,則設置display到元素初始默認,並緩存起來(對文檔片段也是友好的)
show(設置顯示) -> !hidden(本身顯示) :不做處理。下面會路過elem.style.display === 「」 -> values[ index ] || 「」 ,相當於沒處理
!show(設置隱藏)-> hidden(本身隱藏) :display && display !== 「none」,不為」「但仍隱藏,說明這段代碼是為了兼容文檔片段的,會緩存elem.style.display。最終display設為none
!show(設置隱藏)-> !hidden(本身顯示) :緩存css取到的生效樣式,因為style的可能為」「,最終display設為none
show(設置顯示) -> hidden(本身隱藏) :調整為_data緩存中保存的用於顯示的設置;若無緩存,先把display設置為」「,若此時檢測仍為hidden,則設置display到元素初始默認,並緩存起來(對文檔片段也是友好的)
show(設置顯示) -> !hidden(本身顯示) :不做處理。下面會路過elem.style.display === 「」 -> values[ index ] || 「」 ,相當於沒處理
!show(設置隱藏)-> hidden(本身隱藏) :display && display !== 「none」,不為」「但仍隱藏,說明這段代碼是為了兼容文檔片段的,會緩存elem.style.display。最終display設為none
!show(設置隱藏)-> !hidden(本身顯示) :緩存css取到的生效樣式,因為style的可能為」「,最終display設為none
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
定位
jQuery不僅能夠便利的支持快捷的盒模型設置,還提供了兼容的方式獲取定位信息。
jQuery.fn.offset()
無參數時,獲取元素到頁面左上角的距離,包括滾動條。通常通過getBoundingClientRect()獲取相對視口的(對於IE6-8左上角左邊從2,2開始算,所以要減去document.documentElement.clientTop/left),然後加上滾動距離window.pageXOffset/pageYOffset(IE低版本不支持,需要用document.documentElement.scrollTop/scrollLeft,這裡不考慮IE混雜模式),下面還實現了
jQuery.fn.scrollLeft()/scrollTop()
兼容的獲取或設置元素或window的滾動距離,源碼中沒調用這個方法,個人覺得有點奇怪雖然無傷大雅。
支持兩種參數形式(css獲取的position為」static」會設為」relative」),內部調用
對象{left: x, top: x}直接設置
函數fn(i, options),會注入當前位置信息({left: x, top: x})到options,可在函數內修正坐標,之後options會被設置到元素
jQuery.offset.setOffset( elem, options, i )
設置:對象{left: x, top: x}直接設置
函數fn(i, options),會注入當前位置信息({left: x, top: x})到options,可在函數內修正坐標,之後options會被設置到元素
jQuery.fn.position()
讀取基於最近有定位的祖先節點或根節點的border內側的相對偏移,margin部分也算做了元素的一部分,所以偏移量不包含margin。之所以選擇包含margin,是為了css設置top和left定位元素考慮,這樣就不用擔心因為margin的影響要修正top和left了
在原生方法中有elem.offsetLeft、elem.offsetTop,代表相對最近有定位祖先的距離,但是源碼卻沒用它,反而用了更麻煩的方法獲取到元素和有定位祖先的offset()然後相減,原因應該是因為IE低版本的兩個方法有bug,獲取的是相對父集的偏移而無需有定位。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
- 217
- 218
- 219
- 220
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
- 217
- 218
- 219
- 220
- 頂
- 踩