概述

前端在日常工作中很大一部分时间是在思考页面的优化方案,让页面载入得更快。鉴于javascript是单线程的事件驱动语言,优化工作之一就是:控制图片、swf、iframe等大流量文件以及js和css等文件的加载顺序,让它们井然有序的进入到页面中,页面就能尽可能完整的呈现在他们眼前。而为了更好的用户体验,我们要知道每个文件触发onload事件的方案,因为它们在各个浏览器中的表现不尽相同。

iframe的 load 事件

在所有为IFRAME动态添加onload监听事件的方法中,只有 使用事件监听方式为 IFRAME 的 onload 事件绑定处理函数,IE6、7、8才有效。所以为 IFRAME 添加load事件完美方案如下:

1 //事件监听兼容方案
2 functionaddEvent(elem,event,fn){3     if(elem.attachEvent) {4         elem.attachEvent('on'+event,fn)5     } else{6         elem.addEventListener(event,fn,false)7 }8 }9
10 window.onload = function(){11     var iframeA = document.createElement('iframe');12     iframeA.src = 'http://www.baidu.com'
13     addEvent(iframeA,'load',function(){14         document.body.bgColor = '#000'; //回调函数
15 });16 document.body.appendChild(iframeA);17 }

优化页面建议不要嵌套iframe,但是在内部项目还是很常见。其实在IE中,监控iframe加载完毕还可以采取监听 onreadystatechange 事件。

flash 的 load 事件

解决flash的 load主要是两个问题:获取flash对象和flash何时加载完毕。

首先第一个问题:如果object和embed用同样的ID,获取flash对象的时候,IE会认不出。解决方案:

  • js判断IE和非IE,IE中是object,非IE中是embed。
  • 通过flash对象的PercentLoaded方法,检测其值是否为100。

html代码

<div id="load">flash加载中....</div>
<div id="swfWrap"></div>

css代码

#swfWrap{width:200px;height:200px;}
#load{width:200px;color:#fff;text-align:center;background-color:#eee;}

js代码

1 //封装通过ID获取
2 function$(id){3     returndocument.getElementById(id)4 }5
6 var isIE = navigator.appVersion.indexOf("MSIE") != -1 ? true: false;7
8
9 //监听flash是否加载成功
10 functionlistenMovie(flash){11     try{12         return Math.floor(flash.PercentLoaded()) == 100;13     }catch(e){14         return false;15 }16 }17
18 //获取FLASH对象
19 functionthisMovie(movieName) {20     if(isIE) {21         returnwindow[movieName];22 }23     else{24         returndocument[movieName];25 }26 }27
28 //创建flash
29 functioncreateFlash(id,url){30     var html = '<object id="flash" height="200" width="200" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000">'+
31                '<PARAM NAME="FlashVars" VALUE="">'+
32                 '<PARAM NAME="Movie" VALUE="'+url+'">'+
33                 '<PARAM NAME="WMode" VALUE="Transparent">'+
34                 '<PARAM NAME="Quality" VALUE="High">'+
35                 '<PARAM NAME="AllowScriptAccess" VALUE="always">'+
36                 '<embed type="application/x-shockwave-flash" src="'+url+'" id="flashFF" name="flashFF" wmode="window" quality="high" width="200" height="200"></embed>'+
37                 '</object>';38     $(id).innerHTML =html;39 }40
41 window.onload = function(){42     createFlash('swfWrap','flips2.swf')43     var flashObj = isIE ? thisMovie("flash") : thisMovie("flashFF");44     var intervalID =  setInterval(function(){45         if(listenMovie(flashObj)) {46 clearInterval(intervalID);47             intervalID = null;48             $('load').innerHTML = 'flash加载完毕';49 }50     },60)51 }

其中object中的 classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" 不能去掉,不然IE6下会获取取不到flash对象;embed的name值也不能去掉,不然chrome也获取不到。

这里再提下flash的通信的问题,可以参考 这里,解决方法就是将EMBED的 swliveconnect 属性设置成true,然后就可以跟flash通信了。

IMG的 load 事件

img的load事件,我们使用 new Image()。这里我们得注意 complete 事件。研究网上的得出以下代码:

1 var img = newImage();2 img.src= "http://i1.hoopchina.com.cn/user/627/17191627/17191627_big_3.jpg";3 if (img.complete ||img.width) {4     alert("该图片已经在缓存中,不需要再下载")5 alert(img.height)6 } else{7     img.onload = function() {8         alert("图片加载完成");9 alert(img.height)10 }11 }

这里网上很多说法是这样子说的,只要加载过一次图片,img.complete就变成true了,图片就存进浏览器缓存,下次再加载就直接忽略了onload事件,直接从缓存里去读取,而不是再重新去下载。但是我在多个变化条件下(同一个浏览器、同一个标签页、清楚缓存、一个页面存在多个相同图片)测试发现:

在f5刷新后,除了火狐是直接从缓存中读取的,也就是执行 if(img.complete || img.width)语句下的,其他的浏览器都是执行else语句里的代码,重新下载图片;ctrl+f5的话,则所有浏览器都是重新下载图片的。

那么 img.complete 的真正意义在于什么呢?一张页面中,如果存在多个图片地址相同的 img 标签 ,浏览器只会请求一次图片链接,而不是每个img都去请求。

使用 new Image() 请求相同的 gif 图片时,img.complete 貌似不准确,不知道什么原因,难道是因为 gif 动态图是由多张静态图组成?。

而网上说的,将src赋值放在onload事件之后,并不是从根本原因上解决问题。

JS的 load 事件

首先准备一下即将要用到的辅助函数:

1 functiondelay_file(url) {2
3     var type = url.split('.'),4         file = type[type.length - 1];5
6     if (file == 'css') {7         var obj = document.createElement('link'),8             lnk = 'href',9             tp = 'text/css';10         obj.setAttribute('rel', 'stylesheet');11     } else{12         var obj = document.createElement('script'),13             lnk = 'src',14             tp = 'text/javascript';15 }16
17 obj.setAttribute(lnk, url);18     obj.setAttribute('type', tp);19     file == 'css' ? document.getElementsByTagName('head')[0].appendChild(obj) : document.body.appendChild(obj);20     returnobj;21
22 };  

考虑到js加载的特殊性,浏览器引擎在解析js时,对其他资源和文档都会停止。所以我们采用以上方法来异步加载js。而如果想给它增加 回调函数 呢?非IE下 onload 是完美支持的,IE下我们则用 onreadystatechange 事件监听 readyState 值变化。

1  functionloadjs(url, callback) {2
3     var elem =delay_file(url);4     var isIE = navigator.userAgent.indexOf('MSIE') == -1 ? false : true;5
6     if( isIE ) {7         elem.onreadystatechange = function() {8             if (this.readyState && this.readyState == 'loading') return;9             if(callback) {10 callback();11 }12 };13     } else{14         elem.onload = function() {15             if(callback) {16 callback();17 }18 };19 }20
21 }

CSS的 load 事件

CSS 的load事件跟以上讲的 onload 事件兼容性却是相反的,其他浏览器不支持 load 事件,在IE浏览器中反而是支持的。那怎么办呢?

seajs给出了一个方案:

1 functionloadcss(url, callback) {2
3     var elem =delay_file(url);4
5     if(elem.attachEvent) {6         elem.attachEvent('onload', callback);7     } else{8         setTimeout(function() {9 poll(elem, callback);10         }, 0);11 }12
13     functionpoll(_elem, callback) {14
15         var isLoaded = false;16         var sheet = _elem['sheet'];17         var isOldWebKit = (navigator.userAgent.replace(/.*AppleWebKit\/(\d+)\..*/, '$1')) * 1 < 536;18
19         if (isOldWebKit) { //webkit 版本小于 536
20             if(sheet) {21                 isLoaded = true;22 }23         } else if(sheet) {24             try{25                 if(sheet.cssRules) {26                     isLoaded = true;27 }28             } catch(ex) {29                 if (ex.code === 'NS_ERROR_DOM_SECURITY_ERR') {30                     isLoaded = true;31 }32 }33 }34
35         if(isLoaded) {36             setTimeout(function() {37 callback();38             }, 1);39         } else{40             setTimeout(function() {41 poll(_elem, callback);42             }, 1);43 }44 }45
46 }

貌似linkNode在加载前后 linkNode.sheet 和 linkNode.sheet.cssRules 的值会发生变化。我觉得还有一个方法虽然有点绕,但是也是最有效的方法:检测某个类名下的CSS属性是否存。

转载于:https://www.cnblogs.com/zoucaitou/p/4170107.html

js 外部文件加载处理相关推荐

  1. unity异步从外部文件加载音频和图片

    标准的从Resources和Assetbundle读取这里不做介绍了, 主要的应用场景是从互联网http服务器 或者从本地的文件夹读取资源. 音频加载逻辑: 音频是可以直接读取文件后同步返回一个Aud ...

  2. Three.js(十四)—— 模型文件加载

    文章目录 14.Three.js 加载外部模型文件 14.1 Three.js 数据结构.导入导出 Threejs导出模型信息 自定义模型加载器文件 加载Three.js导出的模型数据 14.2 加载 ...

  3. 前端设计中关于外部js文件加载的速度优化

    在一般情况下,许多人都是将<script>写在了<head>标签中,而许多浏览器都是使用单一的线程来加载js文件的,从上往下,从左往右. 若是加载过程出错,那么网页就会阻塞,就 ...

  4. js怎么动态加载js文件(JavaScript性能优化篇)

    下面介绍一种JS代码优化的一个小技巧,通过动态加载引入js外部文件来提高网页加载速度 [基本优化] 将所有需要的<script>标签都放在</body>之前,确保脚本执行之前完 ...

  5. python博客下载本地文件_解决django无法访问本地static文件(js,css,img)网页里js,cs都加载不了...

    1.今天网上下载一个博客项目,发现本地访问,js,css加载不了. 我想应该是项目上线的安全措施,但是我想调试项目.找到方法如下 在settings.py里面编辑 添加 STATICFILES_DIR ...

  6. 解决页面上JS文件加载过慢问题

    解决页面上JS文件加载过慢问题 参考文章: (1)解决页面上JS文件加载过慢问题 (2)https://www.cnblogs.com/zying3/p/10278102.html (3)https: ...

  7. Hive外部分区表加载flume打到hdfs上文件,读不到.tmp文件

    摘要 flume打到hdfs上时,按照文件大小生成文件,在达到指定大小之前数据都是以.tmp文件形式保存在hdfs上,hive外部表也会加载这些文件,但是当文件完成后.tmp会消失,这时候hive会报 ...

  8. 怎么判断一个JS文件加载完成?

    在正常的加载过程中,js的加载都是同步的,也就是说在加载过程中,浏览器会阻塞接下来的内容的加载.这时候我们就要用到动态加载,动态加载是异步的,如果我们在后边要用到这个动态加载的js文件里的东西,就要保 ...

  9. html动态加载js方法,原生JS实现动态加载js文件并在加载成功后执行回调函数的方法...

    本文实例讲述了原生JS实现动态加载js文件并在加载成功后执行回调函数的方法.分享给大家供大家参考,具体如下: 有的时候需要动态加载一个javascript文件,并且在加载成功后执行回调函数(例如文件中 ...

最新文章

  1. bscroll 滚动位置_better-scroll初始滚动位置
  2. webpack中loader加载器(打包非js模块)
  3. android简化log输出方法
  4. How to Pronounce Numbers 20 – 1 Billion
  5. Bob的烦恼II 逃离迷宫
  6. spring cloud config笔记
  7. pyecharts第三节、仪表盘
  8. 在程序里面(服务器端)调用Winrar压缩文件的方法?另寻求一条语句转换的方法。vb.net到C#。...
  9. jvm面试之 Java内存模型之线程独占部分,线程共享部分,常问问题分析
  10. 快速入门开源深度学习框架
  11. 【学习笔记】matlab进行数字信号处理(一)生成信号及信号的时域频域分析
  12. caffe 安装报错解决办法
  13. fu7推挽胆机音质_fu7电子管功放电路图大全(6N8P\6P3P\胆机功放电路\耦合电容器)...
  14. Jinjia2模板控制语句
  15. osm地图数据 mysql_一种OSM地图数据中路网交叉口节点自动合并方法与流程
  16. Java代码实现ping命令
  17. 江南大学计算机科学考研书目,2019江南大学计算机考研初试科目、参考书目、复试线...
  18. BBEdit 10.X for mac的lincese
  19. 如何轻松的破解excel 2016工作表密码
  20. python方差齐性检验_讲讲如何来检验方差齐性

热门文章

  1. Java 中如何使用 SQL 查询文本
  2. 查看linux上面是否有安装redis,redis启动
  3. JS中IE与W3C不同的地方
  4. Puppet基础篇3-安装Puppet前期的准备工作
  5. ExecutorService线程池
  6. 解决mysql无法远程登陆问题
  7. mac地址信息查询站点
  8. 关于Eclipse插件开发(一)
  9. JSP_运维_JSP项目部署到server(适合0经验新手)
  10. CloudCC:为企业业绩而生的CRM系统