动态加载CSS样式表并等待其加载完成

11

我有一个脚本,可以检测按钮点击事件并使用jQuery将CSS样式表附加到"head"中,如下所示:

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. 无法正常工作:

  5.  $(window).load(function () {
         CSSDone();
     });
    
  6. 不能正常工作:

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

相信我,没有什么方法可以解决......


**一个解决方法:**

我在DOM中加载CSS,然后立即使用jQuery将其删除。这样以后将链接添加到头部时就足够快了。


可能是更改CSS链接并等待新CSS加载的重复问题。投票关闭此问题,不是因为这是一个糟糕的问题,而是为了整合信息。 - James McMahon
我宁愿投票关闭另一个问题而不是这个。 - mesqueeb
4个回答

28
纯JavaScript解决方案。
您需要在标签中插入一个节点,然后将事件附加到该节点上。可以将属性分配给一个回调函数,该函数在加载完CSS文件后执行。请参考下面的示例代码,了解如何实现您想要的功能。
let CSSDone = function() {....} // Callback function
let link = document.createElement('link');
link.setAttribute("rel", "stylesheet");
link.setAttribute("type", "text/css");
link.onload = CSSDone; // CSSDone is the callback function
link.setAttribute("href", 'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css');
document.getElementsByTagName("head")[0].appendChild(link);

检查一下jsfiddle
如果你好奇的话,可以参考MDN关于链接元素的参考资料

@mesqueeb,我认为这不会起作用,我认为链接没有onload事件。 - YugoAmaryl
@mok 啊,好吧。反正我也记不起来了。已经过去两年多了 XD - mesqueeb
1
我最终使用了一个hack,通过Image.onerror事件实现。 - YugoAmaryl
3
"link.onload = CSSDone" 这行代码没有必要使用一个什么都不做的匿名函数来调用另一个函数。 - I wrestled a bear once.

2

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


2
为了避免在动态插入样式表链接并依赖这些计算时出现竞争条件:
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,然后将代码作为样式插入而不是链接元素,然后在下一帧解决承诺并从那里继续。

1
您可以尝试这个,我相信..在$("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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接