jQuery 源码解析(二十六) 样式操作模块 样式详解
程序员文章站
2022-08-19 22:03:32
样式操作模块可用于管理DOM元素的样式、坐标和尺寸,本节讲解一下样式相关,样式操作通过jQuery实例的css方法来实现,该方法有很多的执行方法,如下: css(obj) ;参数1是一个对象时,表示一次性设置多个css样式 css(name,func) ;参数2是函数时,设置的是函数返回值 css( ......
样式操作模块可用于管理dom元素的样式、坐标和尺寸,本节讲解一下样式相关,样式操作通过jquery实例的css方法来实现,该方法有很多的执行方法,如下:
- css(obj) ;参数1是一个对象时,表示一次性设置多个css样式
- css(name,func) ;参数2是函数时,设置的是函数返回值
- css(name,'') ;参数2是空字符串时,表示删除该样式(删除style属性上的)
- css(name) ;如果忽略第二个参数,则获取第一个匹配元素的name样式
- css(name,value) ;设置每个匹配的元素的name样式为值value。
writer by:大沙漠 qq:22969969
举个栗子:
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>document</title> <script src="http://libs.baidu.com/jquery/1.7.1/jquery.min.js"></script> <style> div{width: 200px;height: 200px;background: #0ff;} </style> </head> <body> <div> </div> <button id="b1">设置背景和边框</button> <button id="b2">移除边框</button> <button id="b3">获取宽度</button> <script> $('#b1').click(()=>{ $('div').css({background:'#ff0',border:'1px solid #f00'}) }) $('#b2').click(()=>{ $('div').css('border','') }) $('#b3').click(()=>{ $('div').text($('div').css('height') ) }) </script> </body> </html>
效果如下:
我们设置了三个按钮,分别通过css方法进行设置、删除和获取样式,比较好用哈
源码分析
jquery实例css方法实现如下:
jquery.fn.css = function( name, value ) { //获取匹配元素集合中第一个元素的计算样式 或者 在每个匹配元素上设置一个或多个内联样式。 // setting 'undefined' is a no-op if ( arguments.length === 2 && value === undefined ) { return this; } return jquery.access( this, name, value, true, function( elem, name, value ) { //调用jquery.access()遍历匹配元素集合,并在每个元素上执行传入的回调函数 return value !== undefined ? jquery.style( elem, name, value ) : //如果传入了参数则调用jquery.style()设置内联样式 jquery.css( elem, name ); //否则调用jquery.css()来读取计算样式 }); };
通过access工具函数来实现的,这样参数就支持多种形式了,access在html篇里讲解过了,可以看这个地址:
可以源码看到,jquery内部对于css的实现是通过静态的style和css方法来实现的,前者负责设置dom元素的内联样式,后者用于读取elem元素上name的值,style的实现如下:
jquery.extend({ style: function( elem, name, value, extra ) { //读取或设置dom元素的内联样式。elem:dom元素、name:待读取或设置的样式名、value:待设置的样式值、extra:用于指示获取宽度、高度的计算公式字符串。 // don't set styles on text and comment nodes if ( !elem || elem.nodetype === 3 || elem.nodetype === 8 || !elem.style ) { //如果是文本节点或注释节点 或者不是文本、注释节点但是没有style属性 return; //直接返回,不做处理 } // make sure that we're working with the right name var ret, type, origname = jquery.camelcase( name ), style = elem.style, hooks = jquery.csshooks[ origname ]; //将style设置为elem.style name = jquery.cssprops[ origname ] || origname; // check if we're setting a value if ( value !== undefined ) { //如果传入了value值,则设置相对值。 type = typeof value; // convert relative number strings (+= or -=) to relative numbers. #7345 if ( type === "string" && (ret = rrelnum.exec( value )) ) { //如果value是相对值字符串,则计算相对值。value格式是+=..或-=...。rrelnum = /^([\-+])=([\-+.\de]+)/, value = ( +( ret[1] + 1) * +ret[2] ) + parsefloat( jquery.css( elem, name ) ); // fixes bug #9237 type = "number"; } // make sure that nan and null values aren't set. see: #7116 if ( value == null || type === "number" && isnan( value ) ) { //过滤null、nan类型,不做任何处理,如果要删除某个内联样式,请传入空字符串 return; } // if a number was passed in, add 'px' to the (except for certain css properties) if ( type === "number" && !jquery.cssnumber[ origname ] ) { //如果待设置的样式值是一个数值,且该样式不在cssnumber中定义的,则自动追加单位px。cssnumber定义在6492行,是一个数组。 value += "px"; } // if a hook was provided, use that value, otherwise just set the specified value if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value )) !== undefined ) { //优先调用修正对象爱那个的修正方法set(); // wrapped to prevent ie from throwing errors when 'invalid' values are provided // fixes bug #5509 try { style[ name ] = value; //其次设置style[name]属性。 } catch(e) {} } } else { //如果未传入value参数,则读取内联样式。 // if a hook was provided get the non-computed value from there if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) { //优先调用修正对象的get()修正方法,并返回。 return ret; } // otherwise just get the value from the style object return style[ name ]; //没有修正方法则读取属性style[name]。 } }, })
从源码里看到我们可以每次递增一些属性,例如:$("div").css('width','+=20')这样去累加宽度的,默认单位为px。
对于css的实现如下:
jquery.extend({ css: function( elem, name, extra ) { //负责读取dom元素的计算样式。elem:待读取的dom元素,name:待设置的样式名,extra:一个字符串,用于指示获取高度、宽度的计算公式。 var ret, hooks; // make sure that we're working with the right name name = jquery.camelcase( name ); //将样式名转换为驼峰式 hooks = jquery.csshooks[ name ]; //hooks指向驼峰式样式名对应的修正对象。 name = jquery.cssprops[ name ] || name; //修正驼峰式样式名,如果origname是float则把name修正为cssfloat或stylefloat // cssfloat needs a special treatment if ( name === "cssfloat" ) { //如果样式名为cssfloat name = "float"; //则修正为float } // if a hook was provided get the computed value from there if ( hooks && "get" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) { //优先调用修正对象的get()修正方法。 return ret; // otherwise, if a way to get the computed value exists, use that } else if ( curcss ) { return curcss( elem, name ); //其他调用curcss(elem,name)读取计算样式。定义在6765行 } }, })
curcss是jquery内部定义的一个工具函数,用于获取某个样式,实现如下:
curcss = getcomputedstyle || currentstyle;
默认等于getcomputedstyle(window.getcomputedstyle存在的情况下,ie及其它浏览器),currentstyle是jquery内部实现的一个另一个兼容方案,就不讨论了,getcomputedstyle实现如下:
if ( document.defaultview && document.defaultview.getcomputedstyle ) { //在ie9+和其他浏览器中。如果window.getcomputedstyle属性存在。document.defaultview即window对象。 getcomputedstyle = function( elem, name ) { ////定义getcomputedstyle()函数 var ret, defaultview, computedstyle; name = name.replace( rupper, "-$1" ).tolowercase(); //将可能的驼峰式央视名转换为连字符式。rupper = /([a-z]|^ms)/g, if ( (defaultview = elem.ownerdocument.defaultview) && (computedstyle = defaultview.getcomputedstyle( elem, null )) ) { //defaultview即window对象 调用window.getcomputedstyle()方法获取该节点的样式集合 ret = computedstyle.getpropertyvalue( name ); //调用getpropertyvalue()方法获取name样式的值。 if ( ret === "" && !jquery.contains( elem.ownerdocument.documentelement, elem ) ) { //如果没取到计算样式,并且当前元素不再文档中 ret = jquery.style( elem, name ); //调用jquery.style()读取内联样式。 } } return ret; }; }
通过代码可以看到jquery优先调用window.getcomputedstyle()属性获取样式的。
推荐阅读
-
jQuery 源码解析(二十二) DOM操作模块 复制元素 详解
-
jQuery 源码解析(二十九) 样式操作模块 尺寸详解
-
jQuery实现获取及设置CSS样式操作详解
-
jQuery 源码分析(十三) 数据操作模块 DOM属性 详解
-
jQuery 源码解析(二十三) DOM操作模块 替换元素 详解
-
jQuery 源码解析(二十七) 样式操作模块 坐标详解
-
jQuery 源码分析(十二) 数据操作模块 html特性 详解
-
jQuery 源码解析(二十四) DOM操作模块 包裹元素 详解
-
jQuery 源码解析(二十五) DOM操作模块 html和text方法的区别
-
jQuery 源码分析(二十一) DOM操作模块 删除元素 详解