zoukankan      html  css  js  c++  java
  • document.write()的一些坑

      这段时间在做一个广告系统,需要用js自动生成广告代码,其中遇到一些问题,在这记录下。

      第三方广告代码一般都是用 document.write()向页面写入,这次使用的时候遇到不少坑,经常会出现使用document.write()向页面写入的时候当前页面被清空。这正是document.write()的特殊之处,页面载入后浏览器输出流自动关闭,此后对当前页面进行document.write()操作将打开—个新的输出流,它将清除当前页面内容(包括源文档的任何变量或值)。

      那么有哪些浏览器输出流关闭的标识呢?我们首先想到的是 window.onload,在window.onload后页面加载完成,浏览器输出流必然关闭。经测试$(document).ready()中的操 作也是在浏览器输出流关闭之后执行。所以用于生成代码的document.write()不能写在window.onload 和$(document).ready()中。除了这两个之外有没有其他坑呢?js生成广告代码中需要ajax获取服务端的数据,ajax请求成功之后再 document.write()写入仍然会发生覆盖。这是因为jquery的ajax默认是异步请求,并不阻塞文档流,当ajax请求成功之后在执行操 作,浏览器输出流很可能就关闭了。这种情况可以把ajax默认请求改成同步,阻塞文档流,防止document.write()覆盖。

       由于第三方广告代码使用document.write()输出,所有的广告资源都在页面载入时加载,如果页面上第三方广告比较多,必然会阻塞页面加载。有 没有办法在使用document.write()的情况下不阻塞页面加载呢?其实是可以的,这里就需要我们改造原生的document.write()方 法,在广告加载完毕再把原生方法改回来。这里就不具体展开来写,雨夜带刀博客《让document.write的广告无阻塞的加载》有详细分析,这里贴一下带刀改造document.write()的代码。

     1 /**
     2  * 重写document.write实现无阻塞加载script
     3  * @param { Dom Object } textarea元素
     4  */
     5 var loadScript = function( elem ){
     6     var url = elem.value.match( /src="([sS]*?)"/i )[1],
     7         parent = elem.parentNode,
     8         // 缓存原生的document.write
     9         docWrite = document.write,    
    10         // 创建一个新script来加载
    11         script = document.createElement( 'script' ), 
    12         head = document.head || 
    13             document.getElementsByTagName( 'head' )[0] || 
    14             document.documentElement;
    15     
    16     // 重写document.write
    17     document.write = function( text ){
    18         parent.innerHTML = text;
    19     };
    20 
    21     script.type = 'text/javascript';
    22     script.src = url;
    23     
    24     script.onerror = 
    25     script.onload = 
    26     script.onreadystatechange = function( e ){
    27         e = e || window.event;
    28         if( !script.readyState || 
    29         /loaded|complete/.test(script.readyState) ||
    30         e === 'error'
    31         ){
    32 
    33             // 恢复原生的document.write
    34             document.write = docWrite;
    35             head.removeChild( script );
    36             
    37             // 卸载事件和断开DOM的引用
    38             // 尽量避免内存泄漏
    39             head =             
    40             parent = 
    41             elem =
    42             script = 
    43             script.onerror = 
    44             script.onload = 
    45             script.onreadystatechange = null;
    46 
    47         }
    48     }
    49     
    50     // 加载script
    51     head.insertBefore( script, head.firstChild );
    52 };
  • 相关阅读:
    使用Connector/C++(VS2015)连接MySQL的完整例子
    一个表里有多个字段需要同时使用字典表进行关联显示,如何写sql查询语句
    Delphi连接MySql(待测试验证,使用mysql.pas未通过)
    MySQL5.5.51启用网络远程连接
    delphi做的程序如何连接SQL数据库
    定时删除所有文件夹下的_desktop.ini文件
    Delphi中打开网页连接的几种方法
    SQL增删改查
    ADOConnection断线重连
    TDBGridEh 标头排序
  • 原文地址:https://www.cnblogs.com/cuixi/p/4193937.html
Copyright © 2011-2022 走看看