• jQuery源码分析系列:样式表 jQuery.fn.css()


    .css()的用法:

    jQuery.fn.css()有4种用法,第一种是读取样式属性值,其余三种是设置样式属性值

      .css( propertyName ) 获取第一个元素的样式属性值,propertyName是CSS属性名

      .css( propertyName, value ) 在匹配的元素集上设置一个CSS属性,value是要设置的属性值

      .css( propertyName, function(index, value) ) 将函数返回值做为属性值设置

      function(index, value) 返回要设置的属性值,函数的上下文this指向当前元素,接收两个参数:index是当前元素在集合中的下标位置;value是旧值,即当前值(意味着设置之前要先取出当前值)

      .css( map ) 设置多个样式

        map 含有键值对的map,键是属性名,值是字面直接量或函数

    源码分析:.css()方法内部调用.style()用来在DOM节点上读取或设置属性样式 ,用.css()在DOM元素上读取DOM样式值。

    jQuery.fn.css = function( name, value ) {
        //如果有一个参数为undefined 不做任何操作 返回this
        if ( arguments.length === 2 && value === undefined ) {
            return this;
        }
        //对this进行遍历,并执行参数中的函数    调用jQuery.access执行fn
        return jQuery.access( this, name, value, true, function( elem, name, value ) {
            return value !== undefined ?
                //在DOM节点上读取或设置样式属性  style property
                jQuery.style( elem, name, value ) ://设值 包括value是空字符串
                //在DOM元素上读取DOM样式值
                jQuery.css( elem, name );//取值
        });
    };

    .style()方法和.css()方法源码分析:

    JS
    //便于操作的钩子
    jQuery.extend({
        //css钩子
        cssHooks: {
            opacity: {
                get: function( elem, computed ) {
                    if ( computed ) {
                        var ret = curCSS( elem, "opacity", "opacity" );
                        return ret === "" ? "1" : ret;
    
                    } else {
                        return elem.style.opacity;
                    }
                }
            }
        },
        cssNumber: {
            "zIndex": true,
            "fontWeight": true,
            "opacity": true,
            "zoom": true,
            "lineHeight": true,
            "widows": true,
            "orphans": true
        },
        //prop钩子,处理float
        cssProps: {
            "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat"
        },
        /*
            1. 过滤Text和Comment,过滤无style的元素,返回undefined
            2. 转换为驼峰式,修正属性名
            3. 如果是设置:
                    如果是number,过滤NaN;过滤null;如果是相对值字符串,计算
                添加后缀
                如果存在钩子,则调用钩子的set;如果没有钩子,则设置style[ name ] = value;
            4. 如果是读取:
                如果存在钩子,则调用钩子的get;如果没有钩子,则返回style[ name ]
        */
        //在DOM节点上读取或设置样式属性  style property
        style: function( elem, name, value, extra ) {
            //过滤掉text和comment     过滤掉没有style属性的元素
            if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
                return;
            }
    
            //将name转换为驼峰式,修正属性名        确保使用了正确的名字
            var ret, type, origName = jQuery.camelCase( name ),
                style = elem.style, hooks = jQuery.cssHooks[ origName ];//转换为驼峰格式
            //修正属性名,是否在不同的浏览器中使用不同的属性名
            name = jQuery.cssProps[ origName ] || origName;//CSS钩子
    
            //设置
            if ( value !== undefined ) {
                type = typeof value;//值的类型
                /*
                    1.7:
                    if(type === "string" && (ret = rrelNum.test( value )) ){
                        //ret[1]正负号  ret[2]相对值
                        //+(ret[1] + 1  ret[1]是字符串 加上1 变成 +1 或 -1,最后边的加号将字符串转换成1 或 -1
                        //+ret[2]同样将ret[2]转换为数字        parseFloat(jQuery.css(elem,name)):当前值
                        value = (+(ret[1] + 1)* + ret[2]) + parseFloat(jQuery.css(elem,name));
                        type = "number";
                    }
                */
                //过滤NAN null  不做任何处理
                if ( type === "number" && isNaN( value ) || value == null ) {
                    return;
                }
    
                //计算相对值rrelNum = /^([\-+])=([\-+.\de]+)/
                if ( type === "string" && rrelNum.test( value ) ) {
                    value = +value.replace( rrelNumFilter, "" ) + parseFloat( jQuery.css( elem, name ) );
                }
    
                //如果是数字 追加单位px
                if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
                    value += "px";
                }
    
                /*
                 * 如果有钩子hooks,且hooks中存在set函数,则调用hooks.set,将返回值赋给value
                 * 如果hooks.set的返回值为undefined,则不执行任何操作;返回值不为undefined,则用新value设置样式值
                 * 简单点说,有hooks.set则调用,用返回值替换value,最后设置style.name;否则直接设置style.name
                 * 可见钩子的作用是修正属性值,并不直接对值进行设置
                 */
                if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {
                    //用try catch 块 预防IE中用到不合法的值设置样式时,抛出异常
                    try {
                        style[ name ] = value;
                    } catch(e) {}
                }
            //读取
            } else {
                // 如果有钩子hooks,则调用hooks.get,返回值赋给ret
                if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
                    return ret;
                }
                // 否则从style对象中读取属性值
                return style[ name ];
            }
        },
    
        css: function( elem, name, extra ) {
            var ret, hooks;
    
            name = jQuery.camelCase( name );//转换为驼峰式
            hooks = jQuery.cssHooks[ name ];//是否有钩子
            name = jQuery.cssProps[ name ] || name;//修正属性名
    
            //cssFloat特殊处理
            if ( name === "cssFloat" ) {
                name = "float";
            }
            // 如果钩子hooks存在,则调用hooks.get计算样式值,并返回
            if ( hooks && "get" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {
                return ret;
    
            // 否则,如果curCSS存在,则调用curCSS获取计算后的样式值,并返回
            } else if ( curCSS ) {
                return curCSS( elem, name );
            }
        },
    
        // A method for quickly swapping in/out CSS properties to get correct calculations
        swap: function( elem, options, callback ) {
            var old = {};
    
            // Remember the old values, and insert the new ones
            for ( var name in options ) {
                old[ name ] = elem.style[ name ];
                elem.style[ name ] = options[ name ];
            }
    
            callback.call( elem );
    
            // Revert the old values
            for ( name in options ) {
                elem.style[ name ] = old[ name ];
            }
        },
        //将命名规则转换为驼峰式的    ??
        camelCase: function( string ) {
            return string.replace( rdashAlpha, fcamelCase );
        }
    });

    解决浏览器获取属性的兼容问题源码:

    /*
    IE为每个元素提供的currentStyle对象;
    DOM则从document.defaultView对象中访问getComputedStyle()方法;
    
    document.defaultView.getComputedStyle 这是w3c标准方法,取得元素的样式信息,
    因为有些样式是在外部css文件定义的,所以用element.style是取不到的 如果是IE,可以用 element.currentStyle["name"]
    */
    if ( document.defaultView && document.defaultView.getComputedStyle ) {
        getComputedStyle = function( elem, name ) {
            var ret, defaultView, computedStyle;//预定义变量
            //将驼峰式转换成连字符 例如:marginTop > margin-top
            name = name.replace( rupper, "-$1" ).toLowerCase();
            /*
             * 分解:
             * var defaultView = elem && elem.ownerDocument.defaultView;
             * var computedStyle = defaultView && defaultView.getComputedStyle( elem, null );
             * var ret = computedStyle && computedStyle.getPropertyValue( name );
             * return ret;
             */
            if ( (defaultView = elem.ownerDocument.defaultView)&&(computedStyle = defaultView.getComputedStyle( elem, null )) ) {
                ret = computedStyle.getPropertyValue( name );
                if ( ret === "" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {
                    ret = jQuery.style( elem, name );
                }
            }
    
            return ret;
        };
    }
    //IE下
    if ( document.documentElement.currentStyle ) {
        currentStyle = function( elem, name ) {
            var left,
                ret = elem.currentStyle && elem.currentStyle[ name ],//直接取值
                rsLeft = elem.runtimeStyle && elem.runtimeStyle[ name ],
                style = elem.style;
    
            if ( !rnumpx.test( ret ) && rnum.test( ret ) ) {
                // Remember the original values
                left = style.left;
    
                // Put in the new values to get a computed value out
                if ( rsLeft ) {
                    elem.runtimeStyle.left = elem.currentStyle.left;
                }
                style.left = name === "fontSize" ? "1em" : (ret || 0);
                ret = style.pixelLeft + "px";
    
                // Revert the changed values
                style.left = left;
                if ( rsLeft ) {
                    elem.runtimeStyle.left = rsLeft;
                }
            }
    
            return ret === "" ? "auto" : ret;
        };
    }
    
    curCSS = getComputedStyle || currentStyle;
    
    jQuery.curCSS = jQuery.css;



  • 相关阅读:
    DLL注入之Appinit_Dlls
    VC下遍历文件夹中的所有文件的几种方法
    Windows下C语言的Socket编程例子(TCP和UDP)
    Windows进程间共享内存通信实例
    window下线程同步之(Mutex(互斥器) )
    如何安装win10和linux [ubuntu14]双系统
    Windows虚拟地址转物理地址(原理+源码实现,附简单小工具)
    Windows驱动中通过MDL实现用户态与核心态共享内存
    C# Label显示多行文本及换行(WinForm/WebForm)
    使用delegate实现简单的查询功能
  • 原文地址:https://www.cnblogs.com/colorstory/p/2630575.html
Copyright © 2020-2023  润新知