• jQuery 源码解析(二十六) 样式操作模块 样式详解


    样式操作模块可用于管理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篇里讲解过了,可以看这个地址:https://www.cnblogs.com/greatdesert/p/11670682.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()属性获取样式的。

  • 相关阅读:
    mysql
    makefile
    KNN算法(k-nearest neighbor)
    时间序列
    python易错题之lambda 以及 for循环中内嵌函数
    python易错题之作用域
    html----不常见标签
    js----DOM对象(3
    js----DOM对象(事件)
    js----对象
  • 原文地址:https://www.cnblogs.com/greatdesert/p/11890719.html
Copyright © 2020-2023  润新知