【问题标题】:Dark mode flickers a white background for a millisecond on reload黑暗模式在重新加载时闪烁白色背景一毫秒
【发布时间】:2022-04-09 16:31:51
【问题描述】:

我正在尝试在我的应用中添加此暗模式功能。它使用本地存储来存储用户的偏好以供将来使用。所以现在的问题是当暗模式启用时,页面由于某种原因被重新加载,例如。如果用户故意重新加载页面或提交表单,那么在页面变暗之前,整个页面都会出现白色背景的闪烁。它停留了几分之一秒。就是看起来不专业。

尚未找到任何解决方案。所以请帮帮我。

PS。下面的 sn-p 在 SO 中不起作用,因为代码包含 localStorage 对象。

代码如下:

const toggleSwitch = document.querySelector('#dark-mode-button input[type="checkbox"]');
const currentTheme = localStorage.getItem('theme');

if (currentTheme) {
    document.documentElement.setAttribute('data-theme', currentTheme);
    if (currentTheme === 'dark') {
            toggleSwitch.checked = true;
    }
}

function switchTheme(e) {
    if (e.target.checked) {
        document.documentElement.setAttribute('data-theme', 'dark');
        localStorage.setItem('theme', 'dark');
    }else {        
        document.documentElement.setAttribute('data-theme', 'light');
        localStorage.setItem('theme', 'light');
    }    
}

toggleSwitch.addEventListener('change', switchTheme, false);  
:root {
  --primary-color: #495057;
  --bg-color-primary: #F5F5F5;
}

body{
  background-color: var(--bg-color-primary); 
}

[data-theme="dark"] {
  --primary-color: #8899A6;
  --bg-color-primary: #15202B;
}

table {
  font-family: arial, sans-serif;
  border-collapse: collapse;
  width: 100%;
  background-color: #fff;
}

td, th {
  border: 1px solid #dddddd;
  text-align: left;
  padding: 8px;
}
<div id="dark-mode-button">
    <input id="chck" type="checkbox">Dark Mode
    <label for="chck" class="check-trail">
      <span class="check-handler"></span>
    </label>
</div>

<table class="table">
    <thead>
      <tr>
          <th>Header 1</th>
          <th>Header 2</th>
          <th>Header 3</th>
      </tr>
    </thead>  
    <tbody>
      <tr>
        <td>Alfreds Futterkiste</td>
        <td>Maria Anders</td>
        <td>Germany</td>
      </tr>
    </tbody>                     
</table>

【问题讨论】:

  • 这很可能是因为 JS 还没有加载并执行检查。所以页面在正常模式下加载,JS初始化,设置暗模式,然后改变。
  • @EmreKoc 所说的是正确的。我建议将主题检测脚本作为您页面上的第一件事。除此之外,不要在导航时重新加载整个页面 - 只需将更改的部分替换为 ajax 请求即可。
  • 伙计们,对不起,您能告诉我我应该将代码的哪一部分分开,我应该把它放在哪里吗?
  • 移动以阻止渲染的方式设置暗光模式的代码部分 - 意思是,在文档的 &lt;head&gt; 内。像往常一样放置剩余的脚本,就在结束 &lt;/body&gt; 标记之前。这样,浏览器将停止解释您的 JS inside head,并将所需的 data-theme 属性分配给您的 &lt;html&gt; 标签。
  • @RokoC.Buljan 是正确的。但是,考虑到您的querySelector,如果您要优先加载此脚本,您可能需要事件委托

标签: javascript html css


【解决方案1】:

最好通过在文档的&lt;head&gt; 内放置一个小的&lt;script&gt; 标记来阻止页面呈现。通过这样做,渲染器应该停止调用 JavaScript 解释器,将data-theme 属性分配给&lt;html&gt;,然后从左边继续。试试看:

将这个&lt;script&gt; 放在&lt;head&gt; 中——甚至在&lt;link&gt;&lt;style&gt; 标签之前:

<head>
  <!-- meta, title etc... -->

  <script>
  // Render blocking JS:
  if (localStorage.theme) document.documentElement.setAttribute("data-theme", localStorage.theme);
  </script>

  <!-- link, style, etc... -->
</head>

然后,在关闭 &lt;/body&gt; 标记之前以非渲染阻塞的方式使用所有其他脚本:


<!-- other <script> tags here -->

<script>
const toggleSwitch = document.querySelector('#dark-mode-button input[type="checkbox"]');

if (localStorage.theme) {
  toggleSwitch.checked = localStorage.theme === "dark";
}

function switchTheme(e) {
  const theme = e.target.checked ? "dark" : "light";
  document.documentElement.setAttribute("data-theme", theme);
  localStorage.theme = theme;
}

toggleSwitch.addEventListener("change", switchTheme);
</script>

    
<!-- Closing </body> goes here -->

【讨论】:

    猜你喜欢
    • 2021-12-30
    • 2020-10-19
    • 2012-02-05
    • 1970-01-01
    • 1970-01-01
    • 2012-04-19
    • 2017-08-24
    • 1970-01-01
    • 2020-09-22
    相关资源
    最近更新 更多