如何判断样式表何时真正加载完
来源:互联网 发布:唱歌 台风 知乎 编辑:程序博客网 时间:2024/06/05 16:54
原文地址:When is a stylesheet really loaded?
require里面css文件加载的插件:https://github.com/guybedford/require-css/blob/master/css.js
我们经常有通过插入一个link节点来加载css文件的需求。通常,我们需要知道文件何时被加载完以进一步做后面的事情,比如执行回调函数等。
长话短说:这个需求的实现真的比它应该有的实现要困难的多,特别是在火狐里面有很多不必要的麻烦。我在此请求代表沮丧的开发人员提出一个请求:火狐4,请在一个样式表加载完毕的时候触发一个load事件。
更新:
如果你认为:“我们坚信这是可以改变的”,请告诉浏览器厂商请按HTML5标准规定,给link元素能触发一个load事件。这里是每个浏览器的bug列表,里面有评论和重现地址:
- WebKit
- Firefox
- Chrome
在试图获取资源的尝试后,如果关键子资源获取到后,如果加载成功了,用户代理必须往队列添加一个任务在在link元素触发一个建单的叫做load的事件。
以上面这种方式,我们看看我们可以有什么。
// my callback function// which relies on CSS being loadedfunction CSSDone() { alert('zOMG, CSS is done');} // load me some stylesheetvar url = "http://tools.w3clubs.com/pagr/1.sleep-1.css", head = document.getElementsByTagName('head')[0]; link = document.createElement('link'); link.type = "text/css";link.rel = "stylesheet"link.href = url; // MAGIC// call CSSDone() when CSS arrives head.appendChild(link);
以下作为奇幻部分的选项,我们从简单且表现很好到荒谬排序:
1、监听link.onload事件;
2、监听link.addEventListener('load');
3、监听link.onreadystatechange;
4、用setTimeout并检查document.styleSheets的变化;
5、用setTimeout并检查你创建的一个元素一个特定元素在有了新的css样式规则后它的样式的变化。
第5条是很疯狂的,假设你有对CSS内容的掌握,忘记它。加上它用setTimeout来检查当前的样式变化,意味着它在刷新回流队列,可能潜在的会变慢。CSS加载完的越慢,回流就越多。因此,不要使用这种方式。
那么,如何实现“魔法”?
// MAGIC // #1 link.onload = function () { CSSDone('onload listener'); } // #2 if (link.addEventListener) { link.addEventListener('load', function() { CSSDone("DOM's load event"); }, false); } // #3 link.onreadystatechange = function() { var state = link.readyState; if (state === 'loaded' || state === 'complete') { link.onreadystatechange = null; CSSDone("onreadystatechange"); } }; // #4 var cssnum = document.styleSheets.length; var ti = setInterval(function() { if (document.styleSheets.length > cssnum) { // needs more work when you load a bunch of CSS files quickly // e.g. loop from cssnum to the new length, looking // for the document.styleSheets[n].href === url // ... // FF changes the length prematurely :() CSSDone('listening to styleSheets.length change'); clearInterval(ti); } }, 10); // MAGIC ends
测试
测试页面在这。我们在加载一个在服务端延迟2秒返回的CSS文件。将上面的事件监听器和超时都附加上去。附加另外一个超时,2秒后给出简单的"... and two seconds later ... "的提示。然后观察结果。
测试结果
1、IE会触发readystatechange和onload事件(几年前测试的,现在懒得测了)。现在IE9 addEventListener也支持了吧?
2、火狐(像以前一样)什么也没触发。它会立即更新document.styleSheets的length属性,而不用等css文件被加载完。因此测试中的输出结果是:
zOMG, CSS #1 is done: listening to styleSheets.length change... and two seconds later ...3、Opera通过onload会触发load以及addEventListener。像火狐一样,他也会增加document.styleSheets.length的值。输出为:
zOMG, CSS #1 is done: listening to styleSheets.length change... and two seconds later ...zOMG, CSS #1 is done: onload listenerzOMG, CSS #1 is done: DOM's load event4、Chrome和Safari不会触发事件,但是只会在文件被加载完的时候更改document.styleSheets的长度值。
... and two seconds later ...zOMG, CSS #1 is done: listening to styleSheets.length change总而言之,除了火狐,在各种浏览器中至少有一种方式能告诉我们样式表何时被加载完。这是令人非常尴尬的。
火狐真的没有希望了吗?
其他
更新:火狐的问题解决了!
var style = document.createElement('style');style.textContent = '@import "' + url + '"'; var fi = setInterval(function() { try { style.sheet.cssRules; // <--- MAGIC: only populated when file is loaded CSSDone('listening to @import-ed cssRules'); clearInterval(fi); } catch (e){}}, 10); head.appendChild(style);
我更新了我的测试,发现它工作的很好。
- 如何判断样式表何时真正加载完
- JavaScript 判断 DOM 何时加载完毕
- JQuery判断子iframe何时加载完成解决方案
- 如何判断flash是否加载完
- 如何判断团队是否真正实施Scrum?
- laravel如何加载样式文件
- “中国芯”何时真正崛起
- 判断多Frame网页是否真正加载完毕(CHtmlView)
- 判断多Frame网页是否真正加载完毕(CHtmlView)
- 判断多Frame网页是否真正加载完毕(CHtmlView) .
- 判断多Frame网页是否真正加载完毕(CHtmlView)
- 判断多Frame网页是否真正加载完毕(CHtmlView)
- 判断多Frame网页是否真正加载完毕(CHtmlView)
- 加载样式表
- 如何判断脚本加载完成
- 如何判断脚本加载完成
- 如何判断脚本加载完成
- 如何判断脚本加载完成
- CoreData做资讯类文章离线下载的持久化处理方案
- mysql时间戳函数
- 黑马程序员 OC语言 - 1 语法概览
- 拖放 和 共享文件夹
- mysql日期转换格式
- 如何判断样式表何时真正加载完
- 人活着系列之芳姐和芳姐的猪(最短路_SPFA+前向星)
- jsp+ajax+js验证用户名是否存在
- 链表的创建、删除、反向(C语言)
- 带内阻塞,带外阻塞 in band out band block level
- 以后开始写博客,作为学习的备忘录
- Netfilter components 相关的比较好的流程图
- Java中字符编码问题
- mysql时区(timezone)转换函数