zoukankan      html  css  js  c++  java
  • 高性能封装检测浏览器支持css3属性函数

    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,一起成长。

  • 相关阅读:
    对象的访问定位——如何找到对象
    对象的结构
    对象在内存中的布局-对象的创建
    java的内存模型--jmm
    redis 持久化之rdb总结
    简单说springmvc的工作原理
    抽象类和接口的区别
    hashcode和equals的作用区别及联系
    DBC物品中打包物品参数设置
    关于GOM引擎启动时显示:windows socket error: 在其上下文中,该请求的地址无效。 (10049), on API 'bind'
  • 原文地址:https://www.cnblogs.com/barrior/p/5112216.html
Copyright © 2011-2022 走看看