qt 加载样式表_何时真正加载样式表?

本文探讨了在QT中按需加载CSS文件时如何确定文件何时加载完成的问题,特别关注Firefox浏览器的处理方式。作者指出Firefox缺乏合适的加载事件,而其他浏览器如Chrome和Safari则会在文件到达时更新样式表状态。最后,文章提供了一个适用于Firefox的解决方案,并呼吁Firefox改进其样式表加载事件的处理。
摘要由CSDN通过智能技术生成
qt 加载样式表

qt 加载样式表

Often we want to load a CSS file on-demand by inserting a link node. And we want to know when the file finished loading in order to call a callback function for example.

通常,我们想通过插入link节点来按需加载CSS文件。 而且我们想知道文件何时完成加载,以调用回调函数。

Long story short: turns out this is harder than it should be and really unnecessary hard in Firefox. I hereby beg on behalf of many frustrated developers: please, Firefox 4, please fire a load event when a stylesheet loads.

长话短说:事实证明,这比应该做的难,而且在Firefox中确实不必要。 我在此代表许多沮丧的开发人员: Firefox 4,请在load样式表时触发load事件。

load event on link elements as the HTML5 standard mandates. Here's the list of bugs for each browser to comment on and point people to:

Here's what the standard says:

"Once the attempts to obtain the resource and its critical subresources are complete, the user agent must, if the loads were successful, queue a task to fire a simple event named load at the link element"

HTML5标准的要求link元素上触发 load事件。 这是每个浏览器要评论并指出人们的错误列表:

标准是这样的:

“一旦完成了获取资源及其关键子资源的尝试,如果加载成功,则用户代理必须将任务排队,以在link元素处触发一个名为load的简单事件。”

With that out of the way, let's see what we have here.

顺便说一句,让我们看看这里有什么。

// my callback function
// which relies on CSS being loaded
function CSSDone() {
  alert('zOMG, CSS is done');
}
  
 
// load me some stylesheet
var 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);

Options for the magic part, sorted from nice-and-easy to ridiculous

魔术部分的选项,从容易到荒谬

  1. listen to link.onload

    link.onload

  2. listen to link.addEventListener('load')

    link.addEventListener('load')

  3. listen to link.onreadystatechange

    link.onreadystatechange

  4. setTimeout and check for changes in document.styleSheets

    setTimeout并检查document.styleSheets更改

  5. setTimeout and check for changes in the styling of a specific element you create but style with the new CSS

    setTimeout并检查您创建的特定元素的样式是否更改,但使用新CSS样式

5th option is too crazy and assumes you have control over the content of the CSS, so forget it. Plus it checks for current styles in a timeout meaning it will flush the reflow queue and can be potentially slow. The slower the CSS to arrive, the more reflows. So, really, forget it.

第5个选项太疯狂了,它假定您可以控制CSS的内容,所以就算了。 另外,它还会检查超时中的当前样式,这意味着它将刷新重排队列,并且可能会变慢。 CSS到达的速度越慢,重排就越多。 所以,真的,算了吧。

So how about implementing the magic?

那么如何实施魔术呢?

  // 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

测试 (Test)

Test page - riiiight here. I'm loading a CSS file delayed two seconds on the server. Attaching all those event listeners and timeouts above. Adding another timeout that just says "... and two seconds later ... " after (you guessed it!) two seconds. Now observing los resultados...

测试页面-在这里。 我在服务器上加载了延迟两秒钟CSS文件。 附加以上所有这些事件侦听器和超时。 在(您猜对了!)两秒钟之后添加另一个超时,该超时仅显示“ ...和两秒钟后...”。 现在观察los resultados ...

结果 (Results)

  • IE fires readystatechange and load (tested years ago, too lazy to test now again). Now with IE9 maybe addEventListener will work too?

    IE会触发readystatechangeload (几年前测试过,太懒了以至于无法再次测试)。 现在使用IE9,也许addEventListener也可以工作吗?

  • Firefox (like before) fires nothing. It updates the length of document.styleSheets immediately, not waiting for the file to actually arrive. So the outcome in my test log is:

    Firefox(如之前)不会触发任何操作。 它会立即更新document.styleSheetslength ,而不必等待文件实际到达。 所以我的测试日志中的结果是:

    zOMG, CSS #1 is done: listening to styleSheets.length change
    ... and two seconds later ...
    
    
  • Opera fires load via onload and via addEventListener too. Like FF it also increments document.styleSheets.length immédiatement. The outcome:

    Opera也通过onloadaddEventListener触发load 。 像FF也增加document.styleSheets.length immédiatement。 结果:

    zOMG, CSS #1 is done: listening to styleSheets.length change
    ... and two seconds later ...
    zOMG, CSS #1 is done: onload listener
    zOMG, CSS #1 is done: DOM's load event
    
  • Chrome and Safari will not fire events but will update document.styleSheets only when the file arrives, yey!

    Chrome和Safari不会触发事件,但只会在文件到达时更新document.styleSheets ,是的!

    ... and two seconds later ...
    zOMG, CSS #1 is done: listening to styleSheets.length change
    

All in all, there's at least one way to tell when the stylesheet is loaded in each browser, except Firefox. Now that's embarrassing.

总而言之,除了Firefox之外,至少有一种方法可以确定何时在每个浏览器中加载样式表。 现在太尴尬了。

Firefox真的没有希望吗? (Is there really no hope for Firefox?)

If you go really crazy than yes - implement magic #5 but it has serious drawbacks.

如果您真的比真正的疯了,那就实施第5点魔术法,但它有严重的弊端。

Otherwise the object trick should do - all browsers seem to fire load and/or readystatechange event consistently. Obviously it's a little more complicated. Although probably not as complicated as monitoring the document.styleSheets collection

否则object技巧应该readystatechange -所有浏览器似乎始终触发load和/或readystatechange事件。 显然,这要复杂一些。 尽管可能没有监视document.styleSheets集合那么复杂

I also tried MozAfterPaint - it might work but didn't for me, because my CSS didn't change anything on the page that required repaint. Obviously not a fit-all solution.

我还尝试了MozAfterPaint-它可能有效,但不适用于我,因为我CSS并未更改需要重绘的页面上的任何内容。 显然不是万能的解决方案。

Another thing that failed was checking document.styleSheets[n].cssRules. Although document.styleSheets.length is updated immediately, I was thinking FF cannot update document.styleSheets[n].cssRules (document.styleSheets[n].sheet.cssRules) until the CSS actually arrives. However since FF 3.5 (or thereabouts) you don't have access to cssRules collection when the file is hosted on a different domain (CDN say). Security thing, you see. Even cssRules.length would've been enough, but nah.

失败的另一件事是检查document.styleSheets[ n ].cssRules 。 尽管document.styleSheets.length立即更新,但我认为FF在CSS实际到来之前无法更新document.styleSheets[ n ].cssRules ( document.styleSheets[ n ].sheet.cssRules )。 但是,从FF 3.5(或cssRules当文件托管在其他域上时,您将无权访问cssRules集合(例如CDN)。 您知道安全性。 甚至cssRules.length就足够了,但是不。

外卖 (Takeaways)

  1. Any ideas about a clever (or not so clever) workaround that lets us figure out when CSS is loaded in FF? Please comment.

    关于聪明(或不太聪明)的变通办法的任何想法都可以让我们弄清楚何时在FF中加载CSS? 请评论。
  2. Libraries can benefit from document.styleSheets.length trick to support Chrome and Safari. I know at least that YUI3 doesn't support callbacks on Y.Get.css() in Safari (nor FF)

    库可以从document.styleSheets.length技巧中受益,以支持Chrome和Safari。 我至少知道Y.Get.css()不支持Safari(也不是FF)中Y.Get.css()上的回调

  3. Firefox 4 must implement load on stylesheets 🙂 No doubt about it. IMO all browsers should fire load on everything related to external resources.

    Firefox 4必须在样式表上实现load 🙂毫无疑问。 IMO所有浏览器都应在与外部资源相关的所有内容上触发load

更新:FF解决了! (UPDATE: FF solved!)

Thanks to Ryan's comment below, Zach and Oleg, turns out there is something that works. And that is:

多亏了Ryan在下面的评论ZachOleg ,才发现有一些可行的方法。 那就是:

  1. you create a style element, not a link

    您创建style元素,而不是link

  2. add @import "URL"

    添加@import "URL"

  3. poll for access to that style node's cssRules collection

    轮询访问该样式节点的cssRules集合

It just happens so that Firefox will not populate this collection until the file arrives!

发生这种情况是为了使Firefox在文件到达之前不会填充此集合!

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);

Updated my test and seems to work just fine.

更新了我的测试,看来一切正常。

Whew!

ew!

I still maintain that this is unnecessarily complex and all browsers should simply fire load event. Seems to me this FF behavior might change at any time, as well as Safari's not populating document.styleSheet

我仍然认为这不必要地复杂,所有浏览器都应该简单地触发load事件。 在我看来,这种FF行为可能随时更改,以及Safari不会填充document.styleSheet

One thing to note: this access to cssRules is not a failure of the same security check that doesn't allow cssRules access with outside domains. In this case we're accessing cssRules of the inline style and that's fine. We still cant access the styles of the @import-ed file from a different domain.

需要注意的一件事:对cssRules访问并不是同一安全检查的失败,该安全检查不允许cssRules访问外部域。 在这种情况下,我们将访问内联style cssRules ,这很好。 我们仍然无法从其他域访问@ import-ed文件的样式。

Side note: makes me wonder - this could be a technique to preload JS without executing too 🙂

旁注:让我纳闷-这可能是一种无需执行太早就预加载JS的技术🙂

Tell your friends about this post on Facebook and Twitter

FacebookTwitter上告诉您的朋友有关此帖子的信息

翻译自: https://www.phpied.com/when-is-a-stylesheet-really-loaded/

qt 加载样式表

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值