jQuery css模块用于css属性的修改操作。
jQuery.fn.css
jQuery.fn.css = function ( name, value ) { // 又是用access来操作 return jQuery.access( this , function ( elem, name, value ) { var styles, len, map = {}, i = 0 ; // 如果name是数组 if ( jQuery.isArray( name ) ) { // 通过getStyles方法返回elem的styles styles = getStyles( elem ); len = name.length; // 创建对应styles的处理函数map for ( ; i < len; i++ ) { map[ name[ i ] ] = jQuery.css( elem, name[ i ], false , styles ); } return map; } // 如果不是数组,则返回jQuery.style或jQuery.css return value !== undefined ? jQuery.style( elem, name, value ) : jQuery.css( elem, name ); }, name, value, arguments.length > 1 ); };
又是通过jQuery.access来遍历和操作属性。
根据value值来判断是返回一个函数数组,还是返回一个函数传入jQuery.access。
主要用到jQuery.css和jQuery.style两个方法。
getStyles
function getStyles( elem ) { return window.getComputedStyle( elem, null ); }
这是一个获取实际css style的方法。
可是……getComputedStyle是啥东西……
getComputedStyle
是一个可以获取当前元素所有最终使用的CSS属性值。返回的是一个CSS样式声明对象([object CSSStyleDeclaration]),只读。
语法:
var
styles = window.getComputedStyle("元素", "伪类");
如果没有伪类,则传null。
实际上就是获取最终浏览器绘制时的css值,因为style不会返回所有css值,只会返回设置的css值,所以需要用该方法来获得所有css值。
限于篇幅本文就不详细解释了,有兴趣的朋友请参见: 获取元素CSS值之getComputedStyle方法熟悉
jQuery.style
jQuery.style = function ( elem, name, value, extra ) { // 不处理text和comment节点 if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || ! elem.style ) { return ; } var ret, type, hooks, // 修正css属性名 origName = jQuery.camelCase( name ), style = elem.style; // jQuery.cssProps是css缓存,如果有则取出值,否则通过vendorPropName函数来得到实际的css名字 name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) ); // 获取必要的钩子 hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; // 如果value已定义 if ( value !== undefined ) { type = typeof value; // 如果value是+=或则-=一个数,则转成对应的数字 if ( type === "string" && (ret = rrelNum.exec( value )) ) { value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) ); // 将其类型改成number type = "number" ; } // 确保NaN和null不被设置 if ( value == null || type === "number" && isNaN( value ) ) { return ; } // 如果value是数字则加上px if ( type === "number" && ! jQuery.cssNumber[ origName ] ) { value += "px" ; } // 修复#8908,IE9的问题,对于克隆的元素清除掉其background时,其原型的background也会被清除 if ( !jQuery.support.clearCloneStyle && value === "" && name.indexOf("background") === 0 ) { style[ name ] = "inherit" ; } // 如果钩子存在,则使用钩子设置值,否则用style[ name ]来设置值 if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) { style[ name ] = value; } } else { // 如果钩子存在,则使用钩子返回值 if ( hooks && "get" in hooks && (ret = hooks.get( elem, false , extra )) !== undefined ) { return ret; } // 否则用style[ name ]来返回值 return style[ name ]; } };
这里面有一个挺有趣的问题。下面两个代码最后结果是多少呢?
alert(("-" + 5) + 6);alert(("-" + 5) * 6);
jQuery.css
jQuery.css = function ( elem, name, extra, styles ) { var val, num, hooks, origName = jQuery.camelCase( name ); // 修正名字name name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) ); // 得到必要的钩子 hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; // 如果有钩子则使用get来获取值 if ( hooks && "get" in hooks ) { val = hooks.get( elem, true , extra ); } // 没有钩子则用curCSS函数获取 if ( val === undefined ) { val = curCSS( elem, name, styles ); } // 将"normal"转成特定的值 if ( val === "normal" && name in cssNormalTransform ) { val = cssNormalTransform[ name ]; } // 是否需要强行转成数字或者true if ( extra === "" || extra ) { num = parseFloat( val ); return extra === true || jQuery.isNumeric( num ) ? num || 0 : val; } return val; };
curCSS函数
var curCSS = function ( elem, name, _computed ) { var width, minWidth, maxWidth, computed = _computed || getStyles( elem ), // 解决IE9的问题,getPropertyValue用IE9中用.css('filter') ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined, style = elem.style; // 如果实际styles数组存在 if ( computed ) { // 如果ret为"",且elem不是子文档(没有style) if ( ret === "" && ! jQuery.contains( elem.ownerDocument, elem ) ) { ret = jQuery.style( elem, name ); } // 支持:Chrome < 17,Safari 5.1 // 来自Dean Edwards帅呆的hack // 将百分比转成更加有用的px if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) { // 记住原始值 width = style.width; minWidth = style.minWidth; maxWidth = style.maxWidth; // 通过改变minWidth、maxWidth、width得到相应的px值 style.minWidth = style.maxWidth = style.width = ret; ret = computed.width; // 再将原来的值赋回去 style.width = width; style.minWidth = minWidth; style.maxWidth = maxWidth; } } return ret; };
Dean Edwards的hack主要利用的是部分浏览器会使用计算值来表示元素宽度,而非使用值。
show & hide
jQuery.fn.show = function () { return showHide( this , true ); };
jQuery.fn.show直接引用showHide函数,jQuery.fn.hide也是一样:
jQuery.fn.hide = function () { return showHide( this ); };
而jQuery.fn. toggle则可接受state或者通过判断当前元素是否hidden,再调用jQuery.fn.show或者jQuery.fn.hide。
jQuery.fn.toggle = function ( state ) { var bool = typeof state === "boolean" ; return this .each( function () { if ( bool ? state : isHidden( this ) ) { jQuery( this ).show(); } else { jQuery( this ).hide(); } }); };
showHide函数
function showHide( elements, show ) { var elem, values = [], index = 0 , length = elements.length; // 遍历所有元素 for ( ; index < length; index++ ) { elem = elements[ index ]; // 如果元素没有style属性,则跳过 if ( ! elem.style ) { continue ; } // 取出保存在缓存的olddisplay值 values[ index ] = jQuery._data( elem, "olddisplay" ); // 如果要显示 if ( show ) { // 通过将display设置成"",来判断""元素是否会显示 if ( !values[ index ] && elem.style.display === "none" ) { elem.style.display = "" ; } // 如果display被设成了"",并且元素隐藏了,则通过css_defaultDisplay设置默认显示方法 if ( elem.style.display === "" && isHidden( elem ) ) { values[ index ] = jQuery._data( elem, "olddisplay" , css_defaultDisplay(elem.nodeName) ); } // 如果缓存没有值,且元素没有隐藏 } else if ( !values[ index ] && ! isHidden( elem ) ) { // 将目前的display值保存入缓存 jQuery._data( elem, "olddisplay", jQuery.css( elem, "display" ) ); } } // 在第二次循环设置display属性,避免不断回流 for ( index = 0; index < length; index++ ) { elem = elements[ index ]; if ( ! elem.style ) { continue ; } if ( !show || elem.style.display === "none" || elem.style.display === "" ) { // 是否要西那是,要显示则设置成缓存值或者"",否则设置为"none" elem.style.display = show ? values[ index ] || "" : "none" ; } } return elements; }