高性能封裝檢測瀏覽器支持css3屬性函數

jopen 8年前發布 | 9K 次閱讀 CSS3 CSS 前端技術

css3出來已經很久了,現在來談判斷瀏覽器是否支持某個css3的屬性雖說有點過時了,但是還是可以談談的,然后,此篇主要談的不是判斷是否支持,而是怎么封裝更好,為什么這么封裝,歡迎吐槽。

入題,判斷瀏覽器是否支持css3 transition,方法很簡單,只需要下面這句代碼就行了:

'transition' in document.body.style

chrome和ie支持document.body,但是Firefox不支持,Firefox支持document.documentElement,對于沒有doctype聲明的ie又不支持document.documentElement。

所以用 創建一個都支持的元素,然后通過 判斷屬性在元素的style里是否存在即可:

'transition' in document.createElement( 'i' ).style

當然這是標準下,對于老點的chrome或者Firefox,它們不支持transition,但是支持帶前綴的transition,比如chrome 里css寫成-webkit-transition: 1s;于是js也需要對這種情況進行判定,向后兼容。

現在貼一段簡潔的封裝代碼,然后再逐步解析,以避免繁雜,產生不了全局觀:

    function cssProperty( attr ){

            var prefix = [ 'O', 'ms', 'Moz', 'Webkit' ],
                length = prefix.length,

                style = document.createElement( 'i' ).style;

            cssProperty =  function( attr ){

                if( attr in style ){

                    return true;

                }

                attr = attr.replace( /^[a-z]/, function( val ){

                    return val.toUpperCase();

                });

                var len = length;

                while( len-- ){

                    if( prefix[ len ] + attr in style ){

                       return true;

                    }

                }

                return false;

            };

            return cssProperty( attr );
        }

接下來是一段一段的解釋。

為什么直接聲明prefix = [ 'O', 'ms', 'Moz', 'Webkit' ]

而不使用字符串切割prefix = 'O ms Moz Webkit'.split( ' ' ),其他人很多都是這樣寫的。

經筆者測試, 測試代碼如下,為了不必要的影響,我兩段代碼一起測試和兩段代碼分別測試都做了觀察,結果無差。

為了偷懶,估計其他瀏覽器應該也是差不多的結果就不做ie的測試了:

測試結果如下,單位ms:

很明顯,直接聲明prefix = [ 'O', 'ms', 'Moz', 'Webkit' ]的代碼執行效率更高。

再看[ 'O', 'ms', 'Moz', 'Webkit' ]是25個字節,'O ms Moz Webkit'.split( ' ' )是28個字節,即便是從文件大小方面,前者也優勝過后者。

然而為什么很多國外包括jQuery源碼里都是用split分割的形式呢?

(ps:jQuery-2.1.3源碼5738行寫cssPrefix時,是用的直接賦值,代碼如右:cssPrefixes = [ "Webkit", "O", "Moz", "ms" ])

原因我猜大概是這樣的:對于分割的字符串種類比較多時,采用split有利于文件字節的減少,而執行效率縮小99999倍后幾乎可以忽略不計,但是對于文件被下載更快,雖說也可以忽略不計,但是選擇這邊比選擇執行效率那邊要好一點吧。

(ps:或許還有個原因就是書寫split的這條代碼方便吧,不像數組那樣,一會單引號,一會逗號方括號的...。如果是為了裝逼就算了)

回歸正題,回歸到我們這里,兩邊我們都勝過,所以,毋庸置疑的就應該選擇前者。

?對于網上有些不緩存而每次去獲取style的代碼,我想說,難道同個瀏覽器環境下,下一秒這個元素的style就變了嗎,難道不同元素它是style也是變的,難道div元素支持transition,其他某個元素就不支持transition了?!

下面這個代碼來自國外的誰(當然中國好像很多都是直接不假思索的就拷貝過來了): http://code.tutsplus.com/tutorials/quick-tip-detect-css3-support-in-browsers-with-javascript--net-16444

?仔細一看,會發現為什么我的排列是這樣的:O ms Moz Webkit,而別人的是這樣的:Webkit Moz O ms;

理由來自 2015年瀏覽器市場份額排行榜: http://tools.yesky.com/420/93749420.shtml

在國內,Opera PC版估計沒什么用,而且它早已轉向webkit內核了,ie就不談了,對于開發者來說坑太多了,看不到好效果就看不到吧,對不起了。

所以,總體來說,排名依次是chrome,Firefox,ie,opera。

在后面的 while 循環 判斷代碼中,是倒序判斷的,所以從執行效率的角度講,

大部分情況是chrome訪問,所以就第一個判斷webkit內核,滿足條件就跳出循環,減少執行,提高運行效率。

?我的代碼里多了 var len = length; 用下面的代碼測試一下,環境是(老版一點的)瀏覽器都只支持帶前綴的這兩個屬性(比如Firefox13),測試國外代碼第二個及以后的alert彈出的都會是false,因為它耗盡了len。

    alert( cssProperty( 'columns' ) )
    alert( cssProperty( 'animation' ) )

?函數封裝如下封裝,如果像國外那種柯里化封裝表示js一加載完就會執行外層的匿名函數,然后把新函數賦值給supports,如果頁面一定會用到檢測函數,那么這種方法與下面的封裝效果無差,但是如果頁面不一定 用到,即cssProperty變成了整站全局函數,或許另多個頁面用到,于是像下面這樣封裝就不會造成函數的自執行,只有第一次調用函數的時候,函數才會執行,然后被賦予新值,詳情可以參考一下《JavaScript高級程序設計第三版》惰性載入函數。

    function cssProperty( attr ){

         //...code

         cssProperty =  function( attr ){

             //...code

         };

         return cssProperty( attr );
    }

最后歡迎訪問我的 Github ,歡迎Star,歡迎Fork,一起成長。

來自: http://www.cnblogs.com/aiweidong/p/5112216.html

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!