Skip to content

Commit 62dd492

Browse files
author
xudanhust
committed
����css����ע��
1 parent 0c85827 commit 62dd492

File tree

1 file changed

+58
-4
lines changed

1 file changed

+58
-4
lines changed

css.js

Lines changed: 58 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ var curCSS, iframe, iframeDoc,
66
// see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
77
rdisplayswap = /^(none|table(?!-c[ea]).+)/,
88
rmargin = /^margin/,
9+
// core_pnum = /[\-+]?(?:\d*\.|)\d+(?:[eE][\-+]?\d+|)/.source,
910
rnumsplit = new RegExp( "^(" + core_pnum + ")(.*)$", "i" ),
1011
rnumnonpx = new RegExp( "^(" + core_pnum + ")(?!px)[a-z%]+$", "i" ),
1112
rrelNum = new RegExp( "^([-+])=(" + core_pnum + ")", "i" ),
@@ -23,15 +24,18 @@ var curCSS, iframe, iframeDoc,
2324
eventsToggle = jQuery.fn.toggle;
2425

2526
// return a css property mapped to a potentially vendor prefixed property
27+
// 获取css属性名
2628
function vendorPropName( style, name ) {
2729

2830
// shortcut for names that are not vendor prefixed
31+
// 简单处理不带前缀的属性名
2932
if ( name in style ) {
3033
return name;
3134
}
3235

3336
// check for vendor prefixed names
34-
var capName = name.charAt(0).toUpperCase() + name.slice(1),
37+
// 带前缀的属性名
38+
var capName = name.charAt(0).toUpperCase() + name.slice(1), // 第一个字母大写
3539
origName = name,
3640
i = cssPrefixes.length;
3741

@@ -45,33 +49,43 @@ function vendorPropName( style, name ) {
4549
return origName;
4650
}
4751

52+
// 判断节点是否隐藏
53+
// 为什么用两个参数?
4854
function isHidden( elem, el ) {
4955
elem = el || elem;
56+
// elem.ownerDocument 返回elem的根节点,即document
57+
// 所以这里后半句为判断此elem是否包含在document中,若不包含,jQuery就认为它是隐藏的。
5058
return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
5159
}
5260

61+
// 显示或隐藏节点
5362
function showHide( elements, show ) {
5463
var elem, display,
5564
values = [],
5665
index = 0,
5766
length = elements.length;
5867

68+
// 第一次遍历节点
5969
for ( ; index < length; index++ ) {
6070
elem = elements[ index ];
71+
// 没有style属性
6172
if ( !elem.style ) {
6273
continue;
6374
}
75+
// 取出保存在缓存的olddisplay值
6476
values[ index ] = jQuery._data( elem, "olddisplay" );
6577
if ( show ) {
6678
// Reset the inline display of this element to learn if it is
6779
// being hidden by cascaded rules or not
80+
// 通过将display设置成空字符,来判断节点是否会显示
6881
if ( !values[ index ] && elem.style.display === "none" ) {
6982
elem.style.display = "";
7083
}
7184

7285
// Set elements which have been overridden with display: none
7386
// in a stylesheet to whatever the default browser style is
7487
// for such an element
88+
// 如果display被设成了空字符,并且节点是隐藏的,则通过css_defaultDisplay把display默认值缓存起来
7589
if ( elem.style.display === "" && isHidden( elem ) ) {
7690
values[ index ] = jQuery._data( elem, "olddisplay", css_defaultDisplay(elem.nodeName) );
7791
}
@@ -86,12 +100,14 @@ function showHide( elements, show ) {
86100

87101
// Set the display of most of the elements in a second loop
88102
// to avoid the constant reflow
103+
// 第二次遍历节点时设置display,避免不断reflow
89104
for ( index = 0; index < length; index++ ) {
90105
elem = elements[ index ];
91106
if ( !elem.style ) {
92107
continue;
93108
}
94109
if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
110+
// 如果要显示,则设置为缓存值或者空字符,否则设置为none
95111
elem.style.display = show ? values[ index ] || "" : "none";
96112
}
97113
}
@@ -100,12 +116,23 @@ function showHide( elements, show ) {
100116
}
101117

102118
jQuery.fn.extend({
119+
// 对外提供的接口,读取/设置节点样式
120+
// 方式1:$('header').css('height')
121+
// 方式2:$('header').css('height', '20px')
122+
// 方式3:$('header').css(attr, function(index,oldValue){})
123+
// 方式4:$('header').css({'height':'10px', 'width':'20px'})
103124
css: function( name, value ) {
125+
// jQuery.access是一个多功能内部方法,神一样的代码
126+
// 此处需要比较需要关心的是 function( elem, name, value ) 这个匿名方法
127+
// 在jQuery.access经过各种判断检测后,最终就是调用这个匿名方法,遍历this,进行样式读取、设置
128+
// elem:设置/读取样式的节点
129+
// name:样式名
130+
// value:样式值
104131
return jQuery.access( this, function( elem, name, value ) {
105132
return value !== undefined ?
106-
jQuery.style( elem, name, value ) :
107-
jQuery.css( elem, name );
108-
}, name, value, arguments.length > 1 );
133+
jQuery.style( elem, name, value ) : // 设置样式,方式2、3、4的最终归宿
134+
jQuery.css( elem, name ); // 读取样式,方式1的最终归宿
135+
}, name, value, arguments.length > 1 ); // arguments.length > 1 即 value !== undefined,jQuery.access中的参数为chainable,设置样式的时候实现链式调用。但实际上如果采用css({'height':'10px', 'width':'20px'})这种方式来设置,arguments.length == 1,jQuery.access内部对这种情况做了特殊处理,chainable继续为true
109136
},
110137
show: function() {
111138
return showHide( this, true );
@@ -166,24 +193,30 @@ jQuery.extend({
166193
},
167194

168195
// Get and set the style property on a DOM Node
196+
// 读取和设置DOM节点的style属性
169197
style: function( elem, name, value, extra ) {
170198
// Don't set styles on text and comment nodes
199+
// 过滤掉文本和注释节点以及没有style属性的节点
200+
// nodeType = 3,文本;8,注释;
171201
if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
172202
return;
173203
}
174204

175205
// Make sure that we're working with the right name
206+
// 修正属性名
176207
var ret, type, hooks,
177208
origName = jQuery.camelCase( name ),
178209
style = elem.style;
179210

211+
//jQuery.cssProps中如果有则取出,否则通过vendorPropName方法来得到实际的css属性名,并缓存在jQuery.cssProps中
180212
name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );
181213

182214
// gets hook for the prefixed version
183215
// followed by the unprefixed version
184216
hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
185217

186218
// Check if we're setting a value
219+
// 设置属性
187220
if ( value !== undefined ) {
188221
type = typeof value;
189222

@@ -224,6 +257,7 @@ jQuery.extend({
224257
}
225258
},
226259

260+
// 读取节点渲染后的样式值
227261
css: function( elem, name, numeric, extra ) {
228262
var val, num, hooks,
229263
origName = jQuery.camelCase( name );
@@ -282,6 +316,12 @@ jQuery.extend({
282316

283317
// NOTE: To any future maintainer, we've window.getComputedStyle
284318
// because jsdom on node.js will break without it.
319+
// curCSS 为 jQuery.css 的核心方法,获取节点样式
320+
// window.getComputedStyle类似于style,但有区别:
321+
// 1、只读与可写
322+
// 2、获取的对象范围
323+
// 关于window.getComputedStyle,延伸阅读 http://www.zhangxinxu.com/wordpress/2012/05/getcomputedstyle-js-getpropertyvalue-currentstyle/
324+
// IE6-8不支持
285325
if ( window.getComputedStyle ) {
286326
curCSS = function( elem, name ) {
287327
var ret, width, minWidth, maxWidth,
@@ -291,6 +331,9 @@ if ( window.getComputedStyle ) {
291331
if ( computed ) {
292332

293333
// getPropertyValue is only needed for .css('filter') in IE9, see #12537
334+
// getPropertyValue方法可以获取CSS样式对象上的属性值(直接属性名称)
335+
// 这里是针对12537bug的修复 http://bugs.jquery.com/ticket/12537
336+
// bug现象是 element.css('filter') returns undefined in IE9
294337
ret = computed.getPropertyValue( name ) || computed[ name ];
295338

296339
if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
@@ -301,6 +344,7 @@ if ( window.getComputedStyle ) {
301344
// Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right
302345
// Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels
303346
// this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
347+
// 来自Dean Edwards的碉堡了的hack
304348
if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {
305349
width = style.width;
306350
minWidth = style.minWidth;
@@ -318,13 +362,15 @@ if ( window.getComputedStyle ) {
318362
return ret;
319363
};
320364
} else if ( document.documentElement.currentStyle ) {
365+
// currentStyle与getComputedStyle相似,只有IE支持
321366
curCSS = function( elem, name ) {
322367
var left, rsLeft,
323368
ret = elem.currentStyle && elem.currentStyle[ name ],
324369
style = elem.style;
325370

326371
// Avoid setting ret to empty string here
327372
// so we don't default to auto
373+
// 如果currentStyle取不到,尝试用style来取
328374
if ( ret == null && style && style[ name ] ) {
329375
ret = style[ name ];
330376
}
@@ -336,6 +382,8 @@ if ( window.getComputedStyle ) {
336382
// but a number that has a weird ending, we need to convert it to pixels
337383
// but not position css attributes, as those are proportional to the parent element instead
338384
// and we can't measure the parent instead because it might trigger a "stacking dolls" problem
385+
// 又是来自Dean Edwards的碉堡了的hack
386+
// 不规则的像素数字需要额外处理
339387
if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) {
340388

341389
// Remember the original values
@@ -360,6 +408,7 @@ if ( window.getComputedStyle ) {
360408
};
361409
}
362410

411+
// 设置正数
363412
function setPositiveNumber( elem, value, subtract ) {
364413
var matches = rnumsplit.exec( value );
365414
return matches ?
@@ -452,17 +501,21 @@ function getWidthOrHeight( elem, name, extra ) {
452501

453502

454503
// Try to determine the default display value of an element
504+
// 判断一个节点的display默认值
455505
function css_defaultDisplay( nodeName ) {
506+
// 缓存中已有,直接return值
456507
if ( elemdisplay[ nodeName ] ) {
457508
return elemdisplay[ nodeName ];
458509
}
459510

511+
// 向body中添加一个节点,取其display值
460512
var elem = jQuery( "<" + nodeName + ">" ).appendTo( document.body ),
461513
display = elem.css("display");
462514
elem.remove();
463515

464516
// If the simple way fails,
465517
// get element's real default display by attaching it to a temp iframe
518+
// 如果上述方法无效,则创建一个临时的iframe,将节点append到此iframe中,再取其display值
466519
if ( display === "none" || display === "" ) {
467520
// Use the already-created iframe if possible
468521
iframe = document.body.appendChild(
@@ -489,6 +542,7 @@ function css_defaultDisplay( nodeName ) {
489542
}
490543

491544
// Store the correct default display
545+
// 将值缓存起来
492546
elemdisplay[ nodeName ] = display;
493547

494548
return display;

0 commit comments

Comments
 (0)