【问题标题】:Dynamically load css stylesheet and wait for it to load动态加载 css 样式表并等待它加载
【发布时间】:2016-02-26 05:21:37
【问题描述】:

我有一个脚本可以检测按钮点击,它会使用 jQuery 将 CSS 样式表附加到“头部”,如下所示:

const link = "<link class='listcss' rel='stylesheet' href='http://....list.css'>";
$("head").append(link);

那我需要根据css的宽高属性做一些计算:

function CSSDone(){
            if($(window).width()>640){
                $(".grid-item").css({"height":$(".grid-item").width()*0.2});
                $(".grid_item_img").css({"height":$(".grid-item").width()*0.2});
            console.log("a");
            }else{
                $(".grid-item").css({"height":$(".grid-item").width()*0.33});
                $(".grid_item_img").css({"height":$(".grid-item").width()*0.33});
            console.log("b");       
            }
        }
        CSSDone();

但是,如果我启动 CSSDone();添加样式表后,计算发生在加载 css 之前。 我疯狂地在网上搜索,但我尝试的一切都不起作用:

我尝试了以下选项:

  1. 不起作用:

    link.onload = function () { CSSDone(); }

  2. 不起作用:

     if (link.addEventListener) {
       link.addEventListener('load', function() {
         CSSDone();
       }, false);
     }
    
  3. 不起作用:

     link.onreadystatechange = function() {
       var state = link.readyState;
       if (state === 'loaded' || state === 'complete') {
         link.onreadystatechange = null;
         CSSDone();
       }
     };
    
  4. 不起作用:

     $(window).load(function () {
         CSSDone();
     });
    
  5. 不起作用:

     $(window).bind("load", function() {
         CSSDone();
     });
    

相信我。没有任何作用......


**一种解决方法:**

我在 DOM 中加载 css 并立即使用 jQuery 再次删除它。这样以后在头部添加链接时就足够快了。

【问题讨论】:

标签: jquery css document-ready


【解决方案1】:

您需要在头部插入一个link 节点,然后将onload 事件附加到该节点。在您的代码链接中是一个字符串。请参阅下面的示例代码,了解如何实现您想要的。

var link = document.createElement('link');
link.setAttribute("rel", "stylesheet");
link.setAttribute("type", "text/css");
link.onload = CSSDone;
link.setAttribute("href", 'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css');
document.getElementsByTagName("head")[0].appendChild(link);

检查jsfiddle

MDN reference on Link element以防你好奇

【讨论】:

  • @mesqueeb,我不认为它会起作用,我认为链接没有 onload 事件
  • @mok 好吧。反正我不记得了。两年多了XD
  • 我最终使用了一个 hack,带有 Image.onerror 事件
  • link.onload = CSSDone ....没有理由拥有一个除了调用另一个函数之外什么都没有的匿名函数。
【解决方案2】:

我相信你可以试试这个。在$("head").append(link) 的回调中包含CSSDone() 代码

$(document).ready(function(){
$('.btn').on('click', function(){
link = "<link class='listcss' rel='stylesheet' href='/list.css'>";
        $("head").append(link, function(){
        if($(window).width()>640){
                $(".grid-item").css({"height":$(".grid-item").width()*0.2});
                $(".grid_item_img").css({"height":$(".grid-item").width()*0.2});
            console.log("a");
            }else{
                $(".grid-item").css({"height":$(".grid-item").width()*0.33});
                $(".grid_item_img").css({"height":$(".grid-item").width()*0.33});
            console.log("b");       
            }

        }); // append link

        }); // button click
}); // document ready

【讨论】:

    【解决方案3】:

    使用 jQuery:

    var head = $('head');
    var link = $('<link>')
        .attr('rel', 'stylesheet')
        .attr('type', 'text/css')
        .attr('href', url)
                            .on('load', callback)
                            .on('error', error)
                           .appendTo(head);
    
    

    【讨论】:

      【解决方案4】:

      在动态插入样式表链接并依赖这些计算时绕过竞争条件:

      function downloadCSS(url) {
          function insertCss(code) {
              var style = document.createElement('style');
              style.type = 'text/css';
              style.innerHTML = code;
              document.querySelector("head").appendChild(style);
          }
      
          return new Promise(async (resolve, reject) => {
              try {
                  let src = await axios.get(url);
                  insertCss(src.data);
              } catch (e) {
                  return reject(e);
              }
      
              requestAnimationFrame(function () {
                  resolve();
              });
          });
      }
      
      (async function setup() {
          try {
              await downloadCSS('https://myapp.com/style.css');        
          } catch (e) {
              return reject(e);
          }
          
          //rest of code
      })();
      

      我正在使用 axios 库来处理 HTTP 请求,但你可以使用任何你喜欢的东西。

      这个想法是你等待 downloadCSS 承诺,它会下载你的 CSS 的 url,然后将代码作为样式而不是链接元素插入,然后在下一帧解析承诺并从那里继续。

      【讨论】:

        猜你喜欢
        • 2014-12-18
        • 1970-01-01
        • 1970-01-01
        • 2019-02-19
        • 2012-02-04
        • 1970-01-01
        • 1970-01-01
        • 2017-11-10
        • 2011-07-21
        相关资源
        最近更新 更多