【笔记】jQuery源码(样式)

前言

依旧是来自慕课网jQuery源码解析,自己的整理。目前看来所有的文章其实还是有点乱,后面完了我会好好再整理整理/(ㄒoㄒ)/~~。

定义HTML样式的方法

  • <link/>外部引入
  • <style/>嵌入样式
  • style属性

给一个HTML元素设置css属性,如:

var head= document.getElementById("head");
head.style.width = "20px";
head.style.height = "10px";
head.style.display = "block";

存在的问题:

1.每次只能设置一个,而且每设置一次浏览器要绘制一次(高级的浏览器可能会合并style的次数)

2.style接口只能针对
行类样式,link引入的样式无法获取。

3.样式属性名的兼容问题,比如驼峰,保留字float。

Tip:style的内部属性命名采用的驼峰形式,比如 background-image(backgroundImage),比较特殊的就是float,因为是保留字就换成了cssFloat,IE:styleFloat。对于width、hight这些处理都最好要有一个量度单位。

解决方法:
1.合并cssText。

var head= document.getElementById("head");
head.style.cssText="width:20px;height:10px;display:bolck";

cssText很快捷且所有浏览器都支持。批量操作样式时,cssText只需一次 reflow,提高了页面渲染性能。

2.利用文档碎片。
缺点是样式被整体覆盖,处理的时候要先获取需要保留的样式再拼接。

参考文章:https://www.w3cmm.com/dom/ins…

//使用CSSRules去获得样式(非内联的也可以获得)
//添加新的CSS
function addCSSRule(key, value) {
    //获取最后一个样式表
    var css = document.styleSheets[document.styleSheets.length - 1];
    //如果浏览器支持InsertRule方法则使用这个插入,否则是IE,则使用addRule
    css.cssRules ?
        (css.insertRule(key + "{" + value + "}", css.cssRules.length)) :
        (css.addRule(key, value));
}

//移除CSS
function removeCSSRule(key) {
    for (var i = 0; i < document.styleSheets.length; i++) {
        var css = document.styleSheets[i];
        css.cssRules ?
            (function() {
                for (var j = 0; j < css.cssRules.length; j++) {
                    if (css.cssRules[j].selectorText == key) {
                        css.deleteRule(j);
                    }
                }
            })() :
            (css.removeRule(key));
    }
}

//调用示例
addCSSRule("#a","color:red;background:yellow")
removeCSSRule("#a")

钩子机制

$.cssHooks 对象提供了一种方法通过定义函数来获取和设置特定的CSS值的方法

jQuery提供一个 API 来调用用户自定义的函数,用于扩展,以便获取和设置特定属性值。在 .attr,.prop(),.val()和 .css()的操作中都会引入钩子,钩子都有相似的结构。

var someHook = {
    get: function(elem) {
        // obtain and return a value
        return "something";
    },
    set: function(elem, value) {
        // do something with value
    }
}

钩子用来做啥?
做css3浏览器兼容的时候,需要特定的前缀,比如:

Webkit 内核浏览器:-webkit-border-radius
Firefox 内核浏览器:-moz-border-radius

你可以只传一个border-radius,然后CSS hook可以自动帮你把这些前缀都加上。

我们平做浏览器兼容,一般都是:

if(webkit){
   ........................
}else if(firefox){
  ...........................
}else if(...)

如果我们换成hook的话:

$.cssHooks.borderRadius = {
      get: function( elem, computed, extra ) {
        return $.css( elem, borderRadius );
      },
      set: function( elem, value) {
        elem.style[ borderRadius ] = value;
      }
};

样式操作接口

jQuery操作样式的接口jQuery.fn.cssjQuery.css

jQuery.style( elem, name, value )  //设置值  
jQuery.css( elem, name ) //获取值

以下主要集中讲解关于获取值的过程:

  1. 用户调用css()传值是比较随便,所以先检测是不是驼峰写法:

    origName = jQuery.camelCase( name );

  2. 另外要处理如float这样的特殊值,以及浏览器前缀的问题:

    name = jQuery.cssProps[origName] || (jQuery.cssProps[origName] = vendorPropName(elem.style, origName));

  3. 如果元素是display为none无法获得定位,width、height、margin获取问题也需要被处理,这里就要用到CSS钩子:

每一个特殊的情况都有对应的处理,比如width:

cssHooks = {
    width:{
        get:function(){},
        set:function(){}
    }
}

用户在获取width的时候,可能会有以下几种情况:

    • 元素为display:none,获取不到尺寸
    • jQuery有width、innerWidth、outerWidth等各种不同取值方式
    • 元素被设置css3的盒子模型
    1. 其余元素采用getComputedStyle获取对应的值。

    模拟实现

    //获取最终属性
    var getStyles = function(elem) {
        return elem.ownerDocument.defaultView.getComputedStyle(elem, null);
    };
    
    //返回一个css属性映射到一个浏览器商前缀的属性
    function vendorPropName(style, name) {
        // 不用处理前缀的属性直接返回
        if (name in style) {
            return name;
        }
        //检查前缀,capName把第一个字母大写
        var capName = name[0].toUpperCase() + name.slice(1),
            origName = name,
            i = cssPrefixes.length;
       
        //加上CSS前缀
        while (i--) {
            name = cssPrefixes[i] + capName;
            if (name in style) {
                return name;
            }
        }
    
        return origName;
    }
    
    //获取当前样式
    function curCSS(elem, name, computed) {
        var width, minWidth, maxWidth, ret,
            style = elem.style;
    
        computed = computed || getStyles(elem);
    
        if (computed) {
            ret = computed.getPropertyValue(name) || computed[name];
        }
    
        return ret;
    }
    
    //jQuery.css获取css值
    function css(elem, name, extra, styles) {
        var val, num, hooks,
            //转成驼峰写法(如:background-color -> backgroundColor)
            origName = jQuery.camelCase(name);
    
        //如果是特殊属性float转成cssFloat,以及带有浏览器前缀处理
        name = jQuery.cssProps[origName] || (jQuery.cssProps[origName] = vendorPropName(elem.style, origName));
        
        //处理获取width、height等尺寸属性的情况
        hooks = jQuery.cssHooks[name] || jQuery.cssHooks[origName];
        if (hooks && "get" in hooks) {
            val = hooks.get(elem, true, extra);
        }
        
        //通过computed接口直接获取样式
        if (val === undefined) {
            val = curCSS(elem, name, styles);
        }
        return val;
    }
    

    另外在jQuery原型上的css方法,也就是我们直接调用的那个css()是这样的:

    
    //name:设置的属性名,value:设置的属性值
    css: function( name, value ) {
        return access( this, function( elem, name, value ) {
            var styles, len,
                map = {},
                i = 0;
    
            if ( jQuery.isArray( name ) ) {
                styles = getStyles( elem );
                len = name.length;
    
                for ( ; i < len; i++ ) {
                    map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
                }
    
                return map;
            }
            
            //如果value是undefined说明是获取值,否则是设置值
            return value !== undefined ?
                jQuery.style( elem, name, value ) :
                jQuery.css( elem, name );
        }, name, value, arguments.length > 1 );
    }
        原文作者:MOCHIKO
        原文地址: https://segmentfault.com/a/1190000014216375
        本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
    点赞