【问题标题】:document.stylesheet not updating instantlydocument.stylesheet 没有立即更新
【发布时间】:2020-06-20 14:06:09
【问题描述】:

我正在开发一个静态网站。我正在使用 JavaScript 将 CSS 样式表附加到文档头。在 CSS 加载之后,我会根据元素的位置和尺寸进行一些计算。所以CSS必须先加载再计算。

但问题是 Chrome 浏览器等待脚本执行,虽然它会将样式表附加到头部但实际上并没有下载它,因此 document.stylesheets 不会更新!

这个问题只存在于 chrome 中。 Firefox 会按预期立即下载!

我创建了一个示例代码来轻松演示问题

<!DOCTYPE html>
<head></head>
<body>
    <p id='status'></p>
    <button onclick="updateStatus()">updateStatus</button>
    <script>
        const link = document.createElement('link')
        link.rel = 'stylesheet'
        link.href = './style.css'
        document.head.appendChild(link)
        updateStatus()
        function updateStatus() {
            document.getElementById('status').innerHTML = document.styleSheets.length;
        }
        </script>
</body>
</html>

尝试在 chrome 和 Firefox 中打开这个问题。如果你在 Chrome 中运行 sn-p 它将增加一,这意味着 CSS 稍后加载。另一方面,Firefox 的值没有改变意味着它首先加载了 CSS。

如何强制 chrome 或任何其他浏览器先加载 CSS,然后继续执行 JavaScript?

我尝试将onload 事件(也建议here)附加到样式表并且它可以工作,但是我的代码很大而且用途广泛。我不能把它分成 pre-CSS 和 post-CSS 部分!

【问题讨论】:

    标签: javascript css dynamic-loading


    【解决方案1】:

    当遇到此类问题时,一个简单的解决方法是将文件转换为 .PHP 并使用 wampserver 或类似服务在本地托管它们:)

    chrome不更新的原因是样式保存在缓存中。通过使用 PHP 进行开发,您将强制浏览器每次都刷新样式。

    至少我是这样解决的。

    【讨论】:

    • 我认为您误解了问题。这里的问题不在于缓存刷新。 Chrome 会暂停 CSS 文件,直到 JavaScript 完成。但我希望它立即下载。
    【解决方案2】:

    只需在 url 中使用随机数。 这将阻止浏览器从缓存中加载您的样式表。

    link.href = './style.css?rand=' + Math.random(); 
    

    希望对你有帮助

    【讨论】:

    • 问题根本不在于缓存!
    【解决方案3】:

    您可能正在寻找一种不为人知的 hack 来检测 link 元素何时加载了其内容。

    很遗憾,links 没有“加载”事件;例如,以下回调永远不会运行:

    let link = document.createElement('link');
    link.href = '...';
    link.addEventListener('load', () => { /* ... */ });
    

    聪明的人意识到img元素,另一方面,做提供“加载”事件 - 因此,如果它是一个img标签加载你的样式表资源而不是@987654327 @标签,你就可以看到事件了。

    在这一点上,要让这个 hack 工作,我们唯一需要的额外知识是了解如果img 标签加载了一个不能被解释为图像的资源,它将抛出一个“错误”事件而不是一个“加载”事件。

    因此,奇怪的是,以下代码应该可以让您检测到由您的 link 的 href 标识的资源何时加载:

    let link = document.createElement('link');
    link.rel = '...';
    link.href = '...';
    
    let imgForDetectingLoad = document.createElement('img');
    imgForDetectingLoad.src = link.href; // Load the same resource
    imgForDetectingLoad.addEventListener('error', () => {
      // The `link` element has loaded its content!
    });
    

    【讨论】:

    • onload 在链接上工作正常。这里:jsfiddle.net/1bdjxo9w/1。但是img 或link 上的任何事件都不是问题! load 或 error 仅在资源下载后才能使用!但问题是 Chrome 正在阻止资源下载!这就是问题所在。
    • 您的 jsfiddle 有一个错误 - 应该是 img.onload = () =&gt; console.log('...'),而不是 img.onload = console.log('...')(立即评估 console.log)
    • 注意!我的坏(⌣́_⌣̀)
    【解决方案4】:

    据我所知,您只想先加载 CSS,因此始终获得值 1,因为您加载了一个 CSS - 顺便说一下,它不存在并创建 404 :)

    所以只需使用 setTimeout 让浏览器有机会完成脚本,设置 CSS 信息,然后继续使用 updateStatus 方法:

    setTimeout(updateStatus, 0);
    

    【讨论】:

    • 不,CSS 存在并已加载,但不适用于 DOM。所以事实并非如此,但很好的尝试:)
    猜你喜欢
    • 2013-11-07
    • 2017-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-11
    • 2020-10-09
    相关资源
    最近更新 更多