【笔记】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 );
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值