作者: admin

  • js css禁止选中文本

    禁止文本选中

    如果在做拖拽效果的时候,就会使用禁用文本被选中的功能了。

    对于高版本的浏览器可以用样式来控制

    -webkit-touch-callout:none;
    -moz-user-select: none; /*火狐*/
    -webkit-user-select: none; /*webkit浏览器*/
    -ms-user-select: none; /*IE10*/
    -khtml-user-select: none; /*早期浏览器*/
    user-select: none;

     

    对于低版本IE6-9只能用JS 来控制

     $('#ifr1 .tit')[0].onselectstart = $('#ifr1 .tit')[0].ondrag = function(){ //兼容IE6-9 禁止选择文本
         return false;
     }

     

     

  • html5异步

    优化脚本文件的加载提高页面的加载速度,一直是前端工程师提高页面加载速度很重要的一条。因为涉及到各个浏览器对解析脚本文件的不同机制,以及加载脚本会阻塞其他资源和文件的加载。当浏览器解析器遇到<script>时,会立即加载(加载:下载,解析和执行),浏览器对其他资源和文档的加载会停止。为了提高页面的加载速度,得让JS不阻塞其他资源的加载。

    Webkit 和 Firefox 对JS的执行过程进行了优化,增加了“预解析”这个过程,“预解析”过程不会修改DOM树,所以可以跟其他解析过程并行,该过程由预解析器去完成,而可能会改变DOM树执行过程则由主解析器来完成,在通过解析过程了解JavaScript文章中有提到的JS的“预解析”过程,此过程应该就是由浏览器的预解析器完成,预解析器还负责解析样式表和图片。

    另一方面,浏览器同事请求http的数量也是有一定限制的,加载js不像加载样式那样是并行的。样式表是构建呈现树的一部分,浏览器在解析页面结构是由DOM树和呈现树两部分组成,而解析执行样式表只会改变样式表不会更改DOM树,呈现树跟DOM树虽然是相对应的,但并非一一对应。因此,也就没有必要停止对其他资源和文档的加载了。

    提高页面加载速度的最简单快速的方法就是将脚本文件放到body底部。但这并不是提高页面加载速度最优方案的方案,接下来我们介绍其他方案。

    首先来介绍一下<script>时能让脚本延迟和异步执行的两个属性:defer和async。

    Defer、Async属性

    • defer是html4.0中定义的,该属性使得浏览器能延迟脚本的执行,等文档完成解析完成后会按照他们在文档出现顺序再去下载解析。也就是说defer属性的<script>就类似于将<script>放在body的效果。
    • async是HTML5新增的属性,IE10和浏览器都是支持该属性的。该属性的作用是让脚本能异步加载,也就是说当浏览器遇到async属性的<script>时浏览器加载css一样是异步加载的。

    支持async属性的浏览器貌似没什么问题,但是defer属性在各个浏览器中支持程度有点不同。测试代码如下

    <scripttype="text/javascript"defer>
        alert('defer')</script><scripttype="text/javascript">
        alert('script')</script><scripttype="text/javascript">
        window.onload =function(){
            alert('onload')}</script>
    defer测试代码,可将代码复制到本地自己测试,外部脚本src引入,内联脚本直接粘帖

    运行以上代码,得出以下结论:

    • 外部JS在各个浏览器里运行结果跟定义的执行顺序正常,alert信息会按照 script->defer->onload顺序弹出;
    • 内联脚本,如果脚本都是IE9/8/7/6按照定义的顺序弹出信息,其他浏览器则按照 defer->script->onload 顺序弹出信息,表示defer失效。
    • 而如果有多个内联defer脚本、在body和head都有分布或者在iframe中也有内联defer脚本,则在IE6中表现一致。

    如果想给脚本增加defer属性让其延迟加载的话,最好是外部脚本,内联的defer不仅多数浏览器不支持,而且IE6的表现也不一致。

    所以将脚本放在body底部比给脚本增加defer属性让脚本延迟加载更好,就像yslow建议的那样:put style top,put script bottom。

    浏览器的在遇到defer和async属性的<script>的浏览器执行过程如下(以下摘自javascript权威指南):

    1. WEB浏览器创建Document对象,并且开始解析WEB页面,解析HTML元素和它们的文本内容后添加Element对象和Text节点到文档中。这个过程的readystate的属性值是“loading”
    2. 当HTML解析器遇到没有async和defer属性的<script>时,它把这些元素添加到文档中,然后执行行内或外部脚本。这些脚本会同步执行,并且在脚本下载(如果需要)和执行解析器会暂停。这样脚本就可以用document.write()来把文本插入到输入流中。解析器恢复时这些文本会成为文档的一部分。同步脚本经常单定义函数和注册后面使用的注册事件处理程序,但它们可以遍历和操作文档树,因为在它们执行时已经存在了。这样同步脚本可以看到他自己的<script>元素和它们之前的文档内容
    3. 当解析器遇到了设置async属性的<script>元素时,它开始下载脚本,并继续解析文档。脚本会在它下载完成后尽快执行,但是解析器没有停下来等他下载。异步脚本禁止document.write()方法。它们可以看到自己的<script>元素和它之前的所有文档元素,并且可能或干脆不可能访问其他的文档内容。
    4. 当文档完成解析,document.readyState属性变成“interactive”。
    5. 所有有defer属性的脚本,会被它们在文档的里的出现顺序执行。异步脚本可能也会在这个时间执行。延迟脚本能访问完整的文档树,禁止使用document.write()方法。
    6. 浏览器在Document对象上触发DOMContentLoaded事件。这标志着程序执行从同步脚本执行阶段转到异步事件驱动阶段。但要注意,这时可能还有异步脚本没有执行完成。
    7. 这时,文档已经完全解析完成,但是浏览器可能还在等待其他内容载入,如图片。当所有这些内容完成载入时,并且所有异步脚本完成载入和执行,document.readyState属性变为“complete”,WEB浏览器出发Window对象上的load事件。
    8. 从此刻起,会调用异步事件,以异步响应用户输入事件,网络事件,计算器过期等。

    JS异步加载

    了解浏览器在遇到async、defer属性的脚本执行顺序,我们可以利用这两个属性来改善JS的阻塞问题,使用这两个属性会有几种可能的情况:

    • defer为true:延迟加载脚本,在文档完成解析完成开始执行,并且在DOMContentLoaded事件之前执行完成。
    • async为true:异步加载脚本,下载完毕后再执行,在window的load事件之前执行完成

    利用这两个属性异步加载js,还得了解它们的毛病:

    • 使用defer属性,最好是外部的script
    • 使用defer、async的脚本禁止使用document.write()方法
    • 当脚本尝试访问的样式属性可能尚未加载的样式表时,浏览器会禁止该脚本等待样式表加载完成,这等于样式表阻塞了脚本的执行。所以使用defer、async的脚本最好不要请求样式信息时。

    不管是使用defer还是async属性,都需要首先将页面中的js文件进行整理,各个脚本文件之间的依赖性,哪些文件可以延迟加载等等,做好js代码的合并和拆分,然后再根据页面需要合理的使用这两个属性。defer属性声明这个脚本中将不会有 document.write 或 dom 修改。

    当所有脚本解析完成后,JavaScript进入第二个阶段,这个阶段的是异步的,并且由事件驱动的。在事件驱动阶段,WEB浏览器调用事件处理程序函数,来响应异步发生的事件。调用事件处理函数通常是用户输入,网络活动,运行和JavaScript中的错误来触发。

    通过注册事件处理程序函数来处理程序,注册的事件在发生时异步调用这些函数,setTimeout()和setInterval()也都是异步的。所以页面内容中有内联script放在setTimeout()执行是异步JS的一种方法,当然将代码程序放在DOMReady内执行也是异步加载的方法。两者都将代码执行阶段放在了事件驱动阶段。

    在dom中创建的script标签在浏览器中则是异步,如下:

    function delay_js(src){var objScript = document.createElement('script');
        objScript.setAttribute('src', src);
        objScript.setAttribute('type','text/javascript');
        document.body.appendChild(objScript);return objScript;}
    异步加载JS

    以上代码异步加载的JS下载是跟其他一样是并行的,但是执行阶段还是会阻止页面渲染,延长了window.onload的事件。怎么样才能下载和执行JS都不阻塞页面的渲染呢,如下:

    function loadjs(src, succ){var elem = delay_js(src);if((navigator.userAgent.indexOf('MSIE')==-1)?false:true){
            elem.onreadystatechange =function(){if(/loaded|complete/.test(this.readyState)){
                    succ()}};}else{
            elem.onload =function(){
                succ();}}
        elem.onerror =function(){};}
    JS异步下载+执行方案

    代码分析:

    • 非IE浏览器能捕捉到script的onload事件,而IE捕捉不到 script.onload 事件,所以只能借助script.onreadystatechange.
    • 检测onreadystatechange状态中,IE7/8最后一个状态就只是loaded,而IE6中最后一个状态可能 complete 也可能是loaded,所以用正则loaded|complete两个状态都检测。

    异步加载JS的问题是无法使用 document.write 输出文档内容,因为根本无法确定 document.write 应该输出到什么位置,但还是可以在DOMReady之后执行操作dom

    异步加载的其他方法

    除了DOMContentLoaded 与 OnLoad 事件、async属性以及defer属性script能解决JS异步加载外,还有其他方法可以异步加载JS:

    • 通过ajax获取js内容,然后eval执行。 
      var xhrObj = getXHRObject();
       xhrObj.onreadystatechange =function(){if( xhrObj.readyState !=4)return;eval(xhrObj.responseText);};
       xhrObj.open('GET','A.js',true);
       xhrObj.send('');
    • 通过创建iframe:创建并插入iframe元素。
      var iframe = document.createElement('iframe');
      document.body.appendChild(iframe);var doc = iframe.contentWindow.document;
      doc.open().write('<body onload="insertJS()">');
      doc.close();

      此方法存在跨域问题,如果父页面域名修改,则通过javascript协议执行同样域名升级语句。

    • 页内 js 的内容被注释不会执行,但是在需要的时候去掉注释,eval执行js,
    • 在页面中document.write Script Tag
    • 用 setTimeout 延迟0秒 与 其它方法组合

    还有之前说的事件驱动阶段执行以及增加defer或者async属性都是异步加载JS的方法,用哪一种方法就得我们按照需求各自取舍了。但是不管采用何种方法都不能保证执行顺序,都需要将所有js内容按模块化的方式来切分,哪些模块存在依赖关系,哪些模块可以异步,JS怎么切分得斟酌斟酌再斟酌!而命名空间将如何管理,本文则不继续研究了,等研究完
    requirejs、 commonjs以及 seajs再写一片文章

    http://www.html5jscss.com/js_async.html

  • js 倒计时以及回调

    daojishi

    //倒计时
    function inverted(id,overtime,fn){
      function getRTime(){
        var EndTime= new Date(overtime), //截止时间
            NowTime = new Date(),
            t =EndTime.getTime() - NowTime.getTime();
    
        var d=Math.floor(t/1000/60/60/24),
            h=Math.floor(t/1000/60/60%24),
            m=Math.floor(t/1000/60%60),
            s=Math.floor(t/1000%60);
    
        $(id+' .t_d').html(d + "天");
        $(id+' .t_h').html(h + "时");
        $(id+' .t_m').html(m + "分");
        $(id+' .t_s').html(s + "秒");
    
    
       if(t<0){
          !fn();
          $(id+' .t_d').html("0天");
          $(id+' .t_h').html("0时");
          $(id+' .t_m').html("0分");
          $(id+' .t_s').html("0秒");
          clearTimeout(timego);
       }
      }
      var timego=setInterval(getRTime,1000);
    }
    
    inverted('#credit_item_info','2016/02/22 17:35:00',function(){ //调用
    //回调函数写这里
    });
    

    倒计时下载

  • is.js-强大的通用js表单验证插件

    is.js

    is.js是一个强大的通用js表单验证工具类。你可以使用js.js来检测任何东西,例如检测所给的值是否为参数,是否是数组,是否是超链接,…,甚至可以检测浏览器类型,正则表达式和数学表达式等等。
    is.js根据检测的类型分为:类型检测、正则表达式检测、算数检测、环境检测、时间检测、Presence检测、对象检测、字符串检测数组检测和配置检测。

    API文档:https://sdeno.com/zp/is_js/is.html