【筆記】jQuery源碼(樣式)

前言

依舊是來自慕課網jQuery源碼解析,本身的整理。目前看來全部的文章其實仍是有點亂,後面完了我會好好再整理整理/(ㄒoㄒ)/~~。css

定義HTML樣式的方法

  • <link/>外部引入
  • <style/>嵌入樣式
  • style屬性

給一個HTML元素設置css屬性,如:html

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

存在的問題:css3

1.每次只能設置一個,並且每設置一次瀏覽器要繪製一次(高級的瀏覽器可能會合並style的次數)
2.style接口只能針對 行類樣式,link引入的樣式沒法獲取。
3.樣式屬性名的兼容問題,好比駝峯,保留字float。

Tip:style的內部屬性命名採用的駝峯形式,好比 background-image(backgroundImage),比較特殊的就是float,由於是保留字就換成了cssFloat,IE:styleFloat。對於width、hight這些處理都最好要有一個量度單位。web

解決方法:
1.合併cssText。瀏覽器

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

cssText很快捷且全部瀏覽器都支持。批量操做樣式時,cssText只需一次 reflow,提升了頁面渲染性能。dom

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瀏覽器兼容的時候,須要特定的前綴,好比:this

Webkit 內核瀏覽器:-webkit-border-radius
Firefox 內核瀏覽器:-moz-border-radius

你能夠只傳一個border-radius,而後CSS hook能夠自動幫你把這些前綴都加上。firefox

咱們平作瀏覽器兼容,通常都是:

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 );
    }
    相關文章
    相關標籤/搜索