【问题标题】:Changing between themes with Javascript使用 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

【问题讨论】:

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

标签: javascript svg setattribute


【解决方案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" alt="sun"/>
  <img class="moon" src="images/moon.svg" alt="moon"/>
</div>
<h1>Mode</h1>

【讨论】:

    【解决方案2】:

    一开始theme.classList是空的

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

    1. theme.classList 变为暗模式
    2. theme.classList 变为暗模式、亮模式
    3. theme.classList 变为 light-mode
    4. 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>

    【讨论】: