javascript创建css、js,onload触发callback兼容主流浏览器的实现
http://www.fantxi.com/blog/archives/load-css-js-callback/
由于需要写个函数,既可以加载css,又可以加载js,所以对各主流浏览器对加载js、css后是否触发onload事件做了个测试。当然,为了兼容,首先要考虑的是会用到onload和onreadystatechange,但他们并不是万能的。加载js文件onload触发callback不算大问题。css比较特殊,因为Webkeit/FF下加载css不会触发onload事件。所以研究了一晚上才找到个兼容的办法,分享如下:
首先测试元素直接写在页面
- <link onload="alert('css onload')" rel="stylesheet" href="http://localhost/css/123.css"/>
- <script onload="alert('js onload')" src="http://localhost/123.js"></script>
- <link onreadystatechange="alert('css readystatechange')" rel="stylesheet" href="http://localhost/css/123.css"/>
- <script onreadystatechange="alert('js readystatechange')" src="http://localhost/123.js"></script>
CSS onload: 支持: IE6-9/OP, 不支持: FF/Webkit(SF/CM)
JS onload: 支持: IE9/OP/FF/Webkit, 不支持: IE6-8
CSS onreadystatechange: 支持: IE6-9, 不支持: OP/FF/Webkit
JS onreadystatechange: 支持: IE6-9, 不支持: OP/FF/Webkit
测试js创建元素
- var doc = document,
- head = doc.getElementsByTagName("head")[0],
- css, js;
- css = doc.createElement('link');
- css.href = 'http://localhost/123.css?2';
- css.rel = 'stylesheet';
- head.appendChild(css);
- js = doc.createElement('script');
- js.src = 'http://localhost/123.js?2';
- head.appendChild(js);
- css.onload = function(){
- alert('css onload')
- }
- js.onload = function(){
- alert('js onload')
- }
- css.onreadystatechange = function(){
- alert('css readystatechange')
- //alert(this.readyState) //IE可以得到loading/complete, OP为undefined
- }
- js.onreadystatechange = function(){
- alert('js readystatechange')
- //alert(this.readyState) //IE可以得到loading/loaded, OP为loaded
- }
CSS/JS onload:(同元素直接写在页面是一样的)
CSS onreadystatechange: 支持: IE6-9/OP, 不支持: FF/Webkit (这里有区别,OP支持js创建的css元素,但readyState为undefined)
JS onreadystatechange: 支持: IE6-9/OP, 不支持: FF/Webkit (这里有区别,OP支持js创建的js元素,readyState为loaded)
所以为了更大的兼容,onload、onreadystatechange都要写上,代码类似下面:
- // 先把js或者css加到页面: head.appendChild(node);
- // onload为IE6-9/OP下创建CSS的时候,或IE9/OP/FF/Webkit下创建JS的时候
- // onreadystatechange为IE6-9/OP下创建CSS或JS的时候
- node.onload = node.onreadystatechange = function(){
- // !this.readyState 为不支持onreadystatechange的情况,或者OP下创建CSS的情况
- // this.readyState === "loaded" 为IE/OP下创建JS的时候
- // this.readyState === "complete" 为IE下创建CSS的时候
- if (!this.readyState || this.readyState === "loaded" || this.readyState === "complete") {
- node.onload = node.onreadystatechange = null; //防止IE内存泄漏
- alert('loaded, run callback');
- }
- }
jquery、kissy的源码,判断加载成功的核心部分差不多都这样实现的。
存在的问题:
1、当浏览器同时支持onload、onreadystatechange的情况会触发上面的函数两次,
比如:
IE9加载JS的时候,会alert两次,加载CSS的时候,alert一次,注释掉“onload、readystatechange=null”,alert两次。
OP加载JS/CSS,alert一次,把“onload、readystatechange=null”注释也会alert两次。
解决:
先在外部设定个变量isLoaded = false;
"if (!this.readyState..."上面加上个判断,如果已经加载成功就返回,比如:if (isLoaded) { return; }
"node.onload =..."上面加上 isLoaded = ture;
JQ有没有加这个我忘记了、KS应该是加了类似的判断了。
2、这个方法加载JS调用callback是兼容性没问题了,但是加载CSS再callback支持情况不同了:
IE6-9/OP可以成功alert,但是FF/Webkit不支持css的onload,解决办法:
2.1、读取cssRules的length来判断是否加载成功,缺点不能跨域读取(非IE)。
- var doc = document,
- head = document.getElementsByTagName( 'head' )[0],
- link = doc.createElement('link');
- //link.href = 'http://xxx.com/123.css'; //跨域
- link.href = 'http://localhost/123.css';
- link.rel = 'stylesheet';
- head.appendChild( link );
- var sheet, cssRules;
- if ( 'sheet' in link ) { //FF/CM/OP
- sheet = 'sheet'; cssRules = 'cssRules';
- }
- else { //IE
- sheet = 'styleSheet'; cssRules = 'rules';
- }
- var _timer1 = setInterval( function() { // 通过定时器检测css是否加载成功
- try {
- if ( link[sheet] && link[sheet][cssRules].length ) { // css被成功加载
- // console.log(link[sheet][cssRules]);
- clearInterval( _timer1 ); // 清除定时器
- clearTimeout( _timer2 );
- alert('loaded, run callback'); // 加载成功执行callback
- }
- } catch( e ) {
- // FF看到的可能的报错:
- //本地:nsresult: "0x8053000f (NS_ERROR_DOM_INVALID_ACCESS_ERR)" ,因为没加载完成还不能读取,加载完毕就不会报错了
- //跨域:Security error, code: "1000" nsresult: "0x805303e8",因为不能跨域读取CSS。。。
- //关于跨域访问:FF/OP/CM都禁止,IE6-9都可以跨域读取css。
- } finally {}
- }, 20 ),
- // 创建超时定时器,如果过10秒没检测到加载成功
- _timer2 = setTimeout( function() {
- clearInterval( _timer1 ); // 清除定时器
- clearTimeout( _timer2 );
- alert('loaded ? run callback'); // 都过了这么长时间了,虽然没判断加载成功也执行callback(这里可能本身就加载失败,也可能是跨域的情况)
- }, 10000 );
- //@See: http://stackoverflow.com/questions/5537622/dynamically-loading-css-file-using-javascript-with-callback-without-jquery
2.2、创建div#hack4loaded,并添加到页面,然后定时读取div的样式,如果样式是css里面设置的就说明加载成功,此方法不存在跨域问题,所有浏览器都OK。(css里面加上一个样式: #hack4loaded{display:none})
- var doc = document,
- head = doc.getElementsByTagName('head')[0],
- link = doc.createElement('link');
- link.href = 'http://localhost/123.css';
- link.rel = 'stylesheet';
- head.appendChild( link );
- var div = document.createElement('div');
- div.id = 'hack4loaded';
- var getStyle = function(name){ //获取css里面设置的元素样式
- if(div.currentStyle){ // IE/OP
- return div.currentStyle[name];
- }else{ // FF/CM
- return div.ownerDocument.defaultView.getComputedStyle(div, null)[name];
- }
- };
- document.body.appendChild(div); // 添加到页面
- //创建定时器,读取创建的div的样式是否是已经在css里面设置好的
- var _timer1= setInterval( function() {
- //console.log(getStyle('display'));
- if ('none' === getStyle('display')) { //样式和css里面设置的一样,说明加载成功
- clearInterval( _timer1 ); // 清除定时器
- clearTimeout( _timer2 );
- div.parentNode.removeChild(div); //移除div
- alert('loaded, run callback'); // 加载成功执行callback
- }
- }, 50 ),
- // 创建超时定时器,防止css文件加载失败的情况
- _timer2 = setTimeout( function() {
- clearInterval( _timer1 ); // 清除定时器
- clearTimeout( _timer2 );
- alert('fail to load'); // 这个没加载成功的可能性很大,再就是网速太慢超时了
- }, 10000 );
所以总结如下:
javascript创建js或者css,可以兼容浏览器在onload时触发callback。
只要把上面的“node.onload = node.onreadystatechange = function()”方法,再结合2.2的创建div#hack4loaded的方法结合再一起,就可以创建一个比较完美的支持加载js、css,并可以在文件加载完毕触发callback的函数。
由于IE/OP支持css的onload,所以写这个方法的时候可以考虑非IE/OP才用2.2的方法判断css加载完成。
javascript创建css、js,onload触发callback兼容主流浏览器的实现的更多相关文章
- 重温JavaScript获取CSS样式的方法(兼容各浏览器)
众所周知,CSS样式有三种类型:行内样式.内部样式和外部样式,JavaScript获取CSS样式时分为两种情况:行内样式获取法 和 非行内样式获取法 . 一.行内样式获取相对简单,通过element. ...
- CSS 实现图片灰度效果 兼容各种浏览器
CSS 实现图片灰度效果 兼容各种浏览器如360浏览器 CSS实现图片灰度效果就是通过CSS样式让彩色图片呈现为灰色,相当于把一张图像的颜色模式调整为灰度,CSS可以通过以下几种方法来实现灰度效果. ...
- 兼容主流浏览器的CSS透明代码
透明往往能产生不错的网页视觉效果下面是兼容主流浏览器的CSS透明代码.transparent_class { filter:alpha(opacity=50); -moz-opacity:0.5; ...
- (转)兼容主流浏览器的CSS透明代码
透明往往能产生不错的网页视觉效果下面是兼容主流浏览器的CSS透明代码.transparent_class { filter:alpha(opacity=50); -moz-opacity:0.5; - ...
- javaScript与css、html常见的兼容
最近几天总是遇到兼容问题,就整理了一下javaScript和html.css出现的常见兼容.有不全面或不对的欢迎大家指正.也希望这条博客可以帮到一些刚学习的前端的朋友. 一.javaScript出现的 ...
- jQuery+CSS 简单代码实现遮罩层( 兼容主流浏览器 )
/* ** jQuery版本:jQuery-1.8.3.min.js ** 浏览器:Chrome( v31.0.1650.63 m ),IE11,Firefox( v32.0.1 ),IETester ...
- js 复制网页内容,兼容各浏览器
因需要做一个js单击,复制当前网页url的功能.使用的是如下的方法,但是只能在ie浏览器下正常使用. 方法如下: function copyURL(){ var clipBoardContent=&q ...
- 基于原生js的返回顶部组件,兼容主流浏览器
基于原生js的返回顶部插件,兼容IE8及以上.FF.chrome等主流浏览器. js文件中封装了getScrollTop()和changeScrollTop()函数分别用于获取滚动条滚动的高度和修改滚 ...
- 兼容主流浏览器的css渐变色
网页中的渐变色区域,渐变色背景,一般都是通过ps图片方法来实现,但是图片放得多了会影响网页的打开速度,本文介绍的就是用纯 CSS 实现 IE .Firefox.Chrome 和 和Safari都支持的 ...
随机推荐
- Egg + Vue 服务端渲染工程化实现
在实现 egg + vue 服务端渲染工程化实现之前,我们先来看看前面两篇关于Webpack构建和Egg的文章: 在 Webpack工程化解决方案easywebpack 文章中我们提到了基于 Vue ...
- 读书笔记之宿舍共享wifi
若有某方面侵权,请邮件1047697114@qq.com,一个工作日即可处理,谢谢 目录一.简单安装虚拟机二.简单设置,开热点! 我没试过那些wifi软件之类的,以下是个人测试的过程 一.简单安装 ...
- 英特尔:不再公布PC处理器多核睿频数据
据了解,以往英特尔官方有三个频率数据:基础主频:Turbo 2.0(多核)频率:以及Turbo 3.0(单核)频率.现在被隐匿的则是Turbo 2.0(多核)频率. 对此,英特尔在回应媒体时表示,给出 ...
- PHP字符串替换str_replace()函数4种用法详解
mixed str_replace ( mixed $search , mixed $replace , mixed $subject [, int &$count ] )该函数返回一个字符串 ...
- MVC中@RenderBody、@RenderSection、@RenderPage、@Html.RenderPartial、Html.RenderAction的作用和区别
1.@RenderBody() 作用和母版页中的服务器控件类似,当创建基于此布局页面的视图时,视图的内容会和布局页面合并,而新创建视图的内容会通过布局页面的@RenderBody()方法呈现在标签 ...
- python 字典详解
1.字典的定义 字典类似于列表,但相对于列表来说字典更加通用,列表的下标必须必须为整数,而字典下标则可以为任意字符串/数字等,不可以是可变数据类型(列表,数组,元组) 字典包含下标(keys)集合和值 ...
- win10 uwp 上传Nuget 让别人用我们的库
Nuget 我们的开发经常使用别人的dll,那么我们需要每次都从网上下载,然后复制到我们的项目, 而不知道我们的dll是否安全? 当我们的库更新的时候,我们又需要从网上搜索,这样不好,于是我们就用Nu ...
- JavaWeb之Maven配置
Maven和C#的nuget类似,可以通过设置就能引入框架等第三方,方便又省事.Java中使用Maven来管理第三方.今天尝试着配置了一下. 一.JDK的安装 关于JDK的安装可以查看百度经验,设置P ...
- [译]ASP.NET Core 2.0 带初始参数的中间件
问题 如何在ASP.NET Core 2.0向中间件传入初始参数? 答案 在一个空项目中,创建一个POCO(Plain Old CLR Object)来保存中间件所需的参数: public class ...
- DES加密And解密
加密分为:单向加密,双向加密和对称加密. 单向加密:通过对数据进行摘要计算生成密文,密文不可逆推还原.算法代表:Base64,MD5,SHA; 双向加密:与单向加密相反,可以把密文逆推还原成明文,双向 ...