Webkit - 动态创建样式表 - 什么时候真正加载?

Dan*_*Dan 8 javascript jquery dom webkit

我有一些代码(它实际上不是我的,但SlickGrid库)创建一个<style>元素,将其插入DOM,然后立即尝试在document.styleSheets集合中查找新的样式表.

在WebKit中,这有时会失败.我实际上并不知道情况如何,但这并不是一贯可重复的.我想我可以通过更改代码解决它,所以load在样式元素上的事件之前不会检查StyleSheet对象,如下所示:

  $style = $("<style type='text/css' rel='stylesheet' />").appendTo($("head"));
  var rules = ...;// code to create the text of the rules here
  if ($style[0].styleSheet) { // IE
    $style[0].styleSheet.cssText = rules.join(" ");
  } else {
    $style[0].appendChild(document.createTextNode(rules.join(" ")));
  }
  $style.bind('load', function() {
          functionThatExpectsTheStylesheet();
  });
Run Code Online (Sandbox Code Playgroud)

和functionThatExpectsTheStylesheet尝试找到实际的样式表对象,如下所示:

    var sheets = document.styleSheets;
    for (var i = 0; i < sheets.length; i++) {
      if ((sheets[i].ownerNode || sheets[i].owningElement) == $style[0]) {
        stylesheet = sheets[i];
        break;
      }
    }
Run Code Online (Sandbox Code Playgroud)

但有时甚至在那一点上,找不到样式表对象.

所以,我的问题是:

  1. load事件实际上不保证styleSheet对象可用吗?这是一个错误吗?
  2. 如果没有,是否有其他条件我可以使用或做我只需要使用超时这样做?
  3. 或者我绑定加载事件的方式有问题,这是我的问题?

Ain*_*aer 6

不幸的是,动态加载CSS样式表仍然是一个充满浏览器怪癖的领域.在Webkit中,<style><link>元素都将loaderror事件加载样式表时.但是,load事件本身仅表示已加载样式表资源,而不一定是已添加它document.styleSheets.

要求,CSS RequireJS装载机通过分支基于的userAgent嗅其加载机制这个问题涉及(这几乎是不可能的特征检测是否<link>标签将触发其load正常的事件).特别是对于Webkit,检测会使用它setTimeout来查找附加StyleSheet对象的时间document.styleSheets

var webkitLoadCheck = function(link, callback) {
  setTimeout(function() {
    for (var i = 0; i < document.styleSheets.length; i++) {
      var sheet = document.styleSheets[i];
      if (sheet.href == link.href)
        return callback();
    }
    webkitLoadCheck(link, callback);
  }, 10);
}
Run Code Online (Sandbox Code Playgroud)

因此,虽然load事件将在Webkit上触发,但为了能够访问相应的StyleSheet实例,它是不可靠的.目前唯一支持样式表load事件的引擎是Firefox 18+.

披露:我是require-css的贡献者

参考文献: