刷新时图标切换消失

Icon toggle disappears on refresh

我正在尝试在黑暗模式项目中切换月亮图标和太阳图标。 original javascript code 只是一个从白天模式切换到黑暗模式的按钮。经过一些研究,我得到了以下代码,它“有点”有效但很粗略;它从白天模式切换到黑暗模式,图标从月亮切换到太阳但是,当我将偏好设置为黑暗模式(或在黑暗模式下刷新页面)后返回页面时,图标消失了。

const btn = document.querySelector(".btn-mode");
const icon = document.querySelector(".mode");
const prefersDarkScheme = window.matchMedia("(prefers-color-scheme: dark)");

const currentTheme = localStorage.getItem("theme");
if (currentTheme == "dark") {
  document.body.classList.toggle("dark-theme");
  icon.classList.toggle("fa-sun-o");
} else if (currentTheme == "light") {
  document.body.classList.toggle("light-theme");
  icon.classList.toggle("fa-moon-o");
}

btn.addEventListener("click", function () {
  if (prefersDarkScheme.matches) {
    document.body.classList.toggle("light-theme");
    var theme = document.body.classList.contains("light-theme")
      ? "light"
      : "dark";
    icon.classList.toggle("fa-sun-o");
  } else {
    document.body.classList.toggle("dark-theme");
    var theme = document.body.classList.contains("dark-theme")
      ? "dark"
      : "light";
    icon.classList.toggle("fa-moon-o");
  }
  localStorage.setItem("theme", theme);
});

知道我在这里遗漏了什么吗?

我创建了一个 codepen 来显示问题

每次要进行切换时,都需要同时切换 class。

您的代码使用了切换方法,就好像它将月亮换成太阳一样,但它实际上只是切换个人 class 是否存在。当我们需要进行更改时,我已经切换了两个 classes,并注释掉了本地存储内容以避免 SO 代码段出现 JS 错误,但除此之外没有更改您的代码。

const btn = document.querySelector(".btn-mode");
const icon = document.querySelector(".mode");
const prefersDarkScheme = window.matchMedia("(prefers-color-scheme: dark)");

// const currentTheme = localStorage.getItem("theme");
// if (currentTheme == "dark") {
//   document.body.classList.toggle("dark-theme");
//   icon.classList.toggle("fa-moon-o");
// }

btn.addEventListener("click", function() {
  if (prefersDarkScheme.matches) {
    document.body.classList.toggle("light-theme");
    var theme = document.body.classList.contains("light-theme") ?
      "light" :
      "dark";
  } else {
    document.body.classList.toggle("dark-theme");
    var theme = document.body.classList.contains("dark-theme") ?
      "dark" :
      "light";
  }
  icon.classList.toggle("fa-moon-o");
  icon.classList.toggle("fa-sun-o");
  // localStorage.setItem("theme", theme);
});
body {
  --text-color: #555;
  --bkg-color: #fff;
}

body.dark-theme {
  --text-color: #999;
  --bkg-color: #222;
}

body {
  background: var(--bkg-color, #fff);
  color: var(--text-color, #555);
}

.btn-mode {
  background: #000;
  font-size: 20px;
  padding: 10px 10px;
  width: 50px;
  cursor: pointer;
  color: #fff;
  display: block;
  text-align: center;
}

.btn-mode:hover {
  color: #da0000;
}
<html>

<head>
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
</head>

<body class="light-theme">
  <h1>Some title</h1>
  <ul>
    <li class="btn-mode">
      <i class="mode fa fa-sun-o"></i>
    </li>
  </ul>
</body </html>

正如其他人所说,您使用的 toggle 方法产生了不一致的行为。

我重构了一下代码:

const btn = document.querySelector(".btn-mode");
const icon = document.querySelector(".mode");
const prefersDarkScheme = window.matchMedia("(prefers-color-scheme: dark)");

const makeDark = () => {
  document.body.classList.add("dark-theme");
  document.body.classList.remove("light-theme");
  icon.classList.add("fa-moon-o");
  icon.classList.remove("fa-sun-o");
}

const makeLight = () => {
  document.body.classList.remove("dark-theme");
  document.body.classList.add("light-theme");
  icon.classList.remove("fa-moon-o");
  icon.classList.add("fa-sun-o");
}

const setPageThemeTo = (newLightDarkState) => {
  newLightDarkState == "dark" ? makeDark() : makeLight();
}

let currentTheme = localStorage.getItem("theme");

if (!currentTheme) {
  currentTheme = prefersDarkScheme.matches ? 'dark' : 'light';
}

setPageThemeTo(currentTheme);

btn.addEventListener("click", function () {
  currentTheme = currentTheme == "dark" ? "light" : "dark";
  localStorage.setItem("theme", currentTheme);
  setPageThemeTo(currentTheme);
});

你可能会进一步干燥它! :)