使用 Javascript 在主题之间切换

Posted

技术标签:

【中文标题】使用 Javascript 在主题之间切换【英文标题】:Changing between themes with Javascript 【发布时间】:2022-01-16 01:38:47 【问题描述】:

我正在尝试在我的网站上进行深色/浅色主题切换。 SVG 文件在每次点击时来回切换,但主题不是每次点击都会切换。

前两次点击 - 主题改变如预期。

第三次和第四次点击 - 每次点击时 SVG 图像仍会改变,但主题不会改变

第五次和第六次点击 - 主题按预期变化,循环重复

html

<div id="themes">
   <img id="current-theme">
</div>

CSS:

body
  background-color: #ccc;


#themes 
  text-align: right;
  margin-right: 10em;
  margin-top: 2em;
  transform: scale(1.5);
  cursor: pointer;


.dark-mode 
  background-color: rgb(65, 65, 65);
  transition: background-color 0.5s ease;

  h1 
    color: white;
  

  h3 
    color: white;
  

  button 
    background-color: white;
    color: black;
  


.light-mode 
  background-color: #ccc;
  transition: background-color 0.5s ease;

  h1 
    color: var(--primary-color);
  

  h3 
    color: black;
  

  button 
    background-color: black;
    color: white;
  

javascript

//default theme is light
document.getElementById("current-theme").src = "images/moon.svg"

var currentTheme = document.getElementById("current-theme");
currentTheme.setAttribute("onClick", "toDarkTheme()");

var theme = document.body;

function toDarkTheme() 

  document.getElementById("current-theme").src = "images/sun.svg";
  theme.classList.toggle("dark-mode");
  //currentTheme.removeAttribute("onClick");
  currentTheme.setAttribute("onClick", "toLightTheme()");


function toLightTheme() 

  document.getElementById("current-theme").src = "images/moon.svg";
  theme.classList.toggle("light-mode");
  //currentTheme.removeAttribute("onClick");
  currentTheme.setAttribute("onClick", "toDarkTheme()");



我在 jsfiddle 中包含了一个代码链接,这样您就可以准确地看到正在发生的事情。感谢您提供的任何帮助/建议!

https://jsfiddle.net/6op0fx7L/2/#&togetherjs=zTrev7ILNd

【问题讨论】:

我不禁认为拥有一个单击处理程序来检查当前主题并切换它会更容易。而不是每次点击都设置一个新的点击事件处理程序。 【参考方案1】:

当您的 JavaScript 过多时,这种错误很典型。在这个例子中,我只是用 body 元素的类名来控制主题。页面中的所有元素都是 body 元素的子元素,因此很容易为它们设置相应的样式。

我插入了两张图片,所以我不需要进一步操作 DOM,然后也根据 body 类名显示/隐藏它们。

//default theme is light
document.body.classList.add("light-mode");

document.getElementById("themes").addEventListener('click', e => 
  if(document.body.classList.contains("light-mode"))
    document.body.classList.replace("light-mode", "dark-mode");
  else
    document.body.classList.replace("dark-mode", "light-mode");
  
);
#themes 
  float: right;
  margin-right: 10em;
  margin-top: 1em;
  transform: scale(1.5);
  cursor: pointer;


.dark-mode #themes img, .light-mode #themes img 
  position: absolute;
  display: none;


.dark-mode #themes img.sun 
  display: block;


.light-mode #themes img.moon 
  display: block;


.dark-mode 
  background-color: rgb(65, 65, 65);
  transition: background-color 0.5s ease;


.dark-mode h1 
  color: white;


.light-mode 
  background-color: #ccc;
  transition: background-color 0.5s ease;


.light-mode h1 
  color: black;
<div id="themes">
  <!--The icon and theme will change on click-->
  <img class="sun" src="images/sun.svg" />
  <img class="moon" src="images/moon.svg" />
</div>
<h1>Mode</h1>

【讨论】:

【参考方案2】:

一开始theme.classList是空的

然后随着每次后续点击,您会获得以下状态更改...

    theme.classList 变为暗模式 theme.classList 变为暗模式、亮模式 theme.classList 变为 light-mode theme.classList 变为空

即暗模式添加或取消暗模式,它对亮模式没有任何作用,反之亦然。

如果您在开始时明确切换灯光模式,则可以同时切换这两个功能。像这样……

//default theme is light
document.getElementById("current-theme").src = "images/moon.svg"

var currentTheme = document.getElementById("current-theme");
currentTheme.setAttribute("onClick", "toDarkTheme()");

var theme = document.body;
theme.classList.toggle("light-mode");

function toDarkTheme() 

  document.getElementById("current-theme").src = "images/sun.svg";
  theme.classList.toggle("dark-mode");
    theme.classList.toggle("light-mode");

  //currentTheme.removeAttribute("onClick");
  currentTheme.setAttribute("onClick", "toLightTheme()");


function toLightTheme() 

  document.getElementById("current-theme").src = "images/moon.svg";
  theme.classList.toggle("light-mode");
    theme.classList.toggle("dark-mode");

  //currentTheme.removeAttribute("onClick");
  currentTheme.setAttribute("onClick", "toDarkTheme()");
body
  background-color: #ccc;


#themes 
  text-align: right;
  margin-right: 10em;
  margin-top: 2em;
  transform: scale(1.5);
  cursor: pointer;


.dark-mode 
  background-color: rgb(65, 65, 65);
  transition: background-color 0.5s ease;

  h1 
    color: white;
  

  h3 
    color: white;
  

  button 
    background-color: white;
    color: black;
  


.light-mode 
  background-color: #ccc;
  transition: background-color 0.5s ease;

  h1 
    color: var(--primary-color);
  

  h3 
    color: black;
  

  button 
    background-color: black;
    color: white;
  
<div id="themes">
  <!--The icon and theme will change on click-->
  <img id="current-theme">
</div>

【讨论】:

以上是关于使用 Javascript 在主题之间切换的主要内容,如果未能解决你的问题,请参考以下文章

RxJS:如何切换以在多个行为主题源之间切换

Qt应用不同的图标主题

TailwindCSS - 在“浅色”、“深色”或“系统设置”之间切换颜色主题

如何在暗模式切换中使用 localStorage?

有啥方法可以使用一段 JavaScript 在两个字符串之间切换?

Xamarin Forms - 告诉 Android 在运行时切换样式主题