jQuery css模块用于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两个方法。
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 = 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 = 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主要利用的是部分浏览器会使用计算值来表示元素宽度,而非使用值。
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(); } }); };
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; }