javascript - Javascript - 每次点击,如何使黑暗模式切换到工作?

  显示原文与译文双语对照的内容

我在构建一个暗模式开关的应用程序,它在第一次点击时起作用,但在那之后,它每次点击都起作用。

这段代码显示了一个复选框。在项目中,它看起来像一个真正的开关)

知道怎么让它在一次点击中工作?


const body = document.getElementById('body');


let currentBodyClass = body.className;


const darkModeSwitch = document.getElementById('darkModeSwitch');



//Dark Mode


function darkMode() {


 darkModeSwitch.addEventListener('click', () => {


 if (currentBodyClass ==="lightMode") {


 body.className = currentBodyClass ="darkMode";


 } else if (currentBodyClass ==="darkMode") {


 body.className = currentBodyClass ="lightMode";


 }


 });


}

#darkModeSwitch {


 position: absolute;


 left: 15px;


 top: 15px;


 }



.darkMode { background-color: black; transition: ease .3s; }


.lightMode { background-color: #FFF; transition: ease .3s; }



#darkModeSwitch input[type="checkbox"] {


 width: 40px;


 height: 20px;


 background: #fff89d;


}



#darkModeSwitch input:checked[type="checkbox"] {


 background: #757575;


}



#darkModeSwitch input[type="checkbox"]:before {


 width: 20px;


 height: 20px;


 background: #fff;


}



#darkModeSwitch input:checked[type="checkbox"]:before {


 background: #000;


}

<body id="body" class="lightMode">



 <div id="darkModeSwitch">


 <input type="checkbox" onclick="darkMode()" title="Toggle Light/Dark Mode" />


 </div>



</body>

时间:

在复选框的每一个点击事件上,你在darkModeSwitch元素上设置一个新的事件监听器,可以删除


const body = document.getElementById('body');


let currentBodyClass = body.className;


const darkModeSwitch = document.getElementById('darkModeSwitch');



//Dark Mode


function darkMode() {



 if (currentBodyClass ==="lightMode") {


 body.className = currentBodyClass ="darkMode";


 } else if (currentBodyClass ==="darkMode") {


 body.className = currentBodyClass ="lightMode";


 }



}

#darkModeSwitch {


 position: absolute;


 left: 15px;


 top: 15px;


 }



.darkMode { background-color: black; transition: ease .3s; }


.lightMode { background-color: #FFF; transition: ease .3s; }



#darkModeSwitch input[type="checkbox"] {


 width: 40px;


 height: 20px;


 background: #fff89d;


}



#darkModeSwitch input:checked[type="checkbox"] {


 background: #757575;


}



#darkModeSwitch input[type="checkbox"]:before {


 width: 20px;


 height: 20px;


 background: #fff;


}



#darkModeSwitch input:checked[type="checkbox"]:before {


 background: #000;


}

<body id="body" class="lightMode">



 <div id="darkModeSwitch">


 <input type="checkbox" onclick="darkMode()" title="Toggle Light/Dark Mode" />


 </div>



</body>

每次单击复选框时,你将向darkModeSwitchaddEventListener将移出函数,并移除

那么,你需要搬家let currentBodyClass = body.className;inside darkModeSwitch函数,以便每次更新值。在函数之外,在运行时给它赋值一次,然后永远不要更新它

最后,这有局限性


body.className = currentBodyClass ="darkMode";



相反,只要


body.className ="darkMode";




const darkModeSwitch = document.getElementById('darkModeSwitch');


const body = document.getElementById('body');



//Dark Mode


darkModeSwitch.addEventListener('click', () => {


 let currentBodyClass = body.className;



 if (body.className ==="lightMode") {


 body.className ="darkMode";


 } else if (currentBodyClass ==="darkMode") {


 body.className ="lightMode";


 }


});

#darkModeSwitch {


 position: absolute;


 left: 15px;


 top: 15px;


}



.darkMode {


 background-color: black;


 transition: ease .3s;


}



.lightMode {


 background-color: #FFF;


 transition: ease .3s;


}



#darkModeSwitch input[type="checkbox"] {


 width: 40px;


 height: 20px;


 background: #fff89d;


}



#darkModeSwitch input:checked[type="checkbox"] {


 background: #757575;


}



#darkModeSwitch input[type="checkbox"]:before {


 width: 20px;


 height: 20px;


 background: #fff;


}



#darkModeSwitch input:checked[type="checkbox"]:before {


 background: #000;


}

<body id="body" class="lightMode">



 <div id="darkModeSwitch">


 <input type="checkbox" title="Toggle Light/Dark Mode" />


 </div>



</body>

虽然这些方法避免了这种情况


let currentBodyClass = body.classList;



if (currentBodyClass.contains("lightMode")) {


 currentBodyClass.add('darkMode');


 currentBodyClass.remove('lightMode');


} else if (currentBodyClass.contains("darkMode")) {


 currentBodyClass.add('lightMode');


 currentBodyClass.remove('darkMode');


}



这更容易使用输入类型进行检查


var isChecked= document.getElementById('input[type="checkbox"]').checked;


if(isChecked){ //checked


 //execute code here


}else{ //unchecked


 //execute code here


}



在回答之前:


<input type="checkbox" onclick="darkMode()" title="Toggle Light/Dark Mode" />



每次单击时调用函数darkMode


function darkMode() {


 darkModeSwitch.addEventListener('click', () => { // you add event listener


 if (currentBodyClass ==="lightMode") {


 body.className = currentBodyClass ="darkMode";


 } else if (currentBodyClass ==="darkMode") {


 body.className = currentBodyClass ="lightMode";


 }


 });


}



它结果是,点击复选框时,你将拥有很多侦听器。

你需要oen来自2个选项:

  • html中的onClick,并删除darkModeSwitch.addEventListener('click', () => {
  • 删除onClickdarkMode函数,并保留darkModeSwitch.addEventListener('click', () => {-这将添加一个侦听器,并处理所有的点击

回到答案,有很多工作答案,我只想在优化上给出一点建议

简化演示:


const body = document.getElementById('body');


const darkModeSwitch = document.getElementById('darkModeSwitch');



// put classes into array


const themeClesses = [`lightMode`, `darkMode`];



//Dark Mode


function darkMode() {


 // simply map through it and toggle


 themeClesses.map(str => body.classList.toggle(str))


}

#darkModeSwitch {


 position: absolute;


 left: 15px;


 top: 15px;


 }



.darkMode { background-color: black; transition: ease .3s; }


.lightMode { background-color: #FFF; transition: ease .3s; }



#darkModeSwitch input[type="checkbox"] {


 width: 40px;


 height: 20px;


 background: #fff89d;


}



#darkModeSwitch input:checked[type="checkbox"] {


 background: #757575;


}



#darkModeSwitch input[type="checkbox"]:before {


 width: 20px;


 height: 20px;


 background: #fff;


}



#darkModeSwitch input:checked[type="checkbox"]:before {


 background: #000;


}

<body id="body" class="lightMode">



 <div id="darkModeSwitch">


 <input type="checkbox" onclick="darkMode()" title="Toggle Light/Dark Mode" />


 </div>



</body>

每次单击按钮时,向开关添加新的事件侦听器,每次你点击按钮的黑暗模式它切换偶数次导致没有改变。

一个简单的方法就是在


let eventCount = 0;


function darkMode() {


 console.log("Event was fired for the" + eventCount +"th time!");


 eventCount++;


 darkModeSwitch.addEventListener('click', () => {


 if (currentBodyClass ==="lightMode") {


 body.className = currentBodyClass ="darkMode";


 } else if (currentBodyClass ==="darkMode") {


 body.className = currentBodyClass ="lightMode";


 }


 });


}



解决方案与建议的其他答案一样,移除方法中的addEventListener调用。

我认为你的问题源于应用两个事件处理程序来促进上下文切换,一个inline和一个通过addEventListener,在状态管理方面,使用checkbox checked状态作为指示器来切换暗模式更符合惯例。


const body = document.getElementById('body');


let currentBodyClass = body.className;


const darkModeSwitch = document.querySelector('#darkModeSwitch input[type="checkbox"]');



darkModeSwitch.addEventListener("click", function(e) {


 var isChecked = e.target.checked;


 if (isChecked) {


 body.className = currentBodyClass ="darkMode";


 } else { //unchecked


 body.className = currentBodyClass ="lightMode";


 }


});

#darkModeSwitch {


 position: absolute;


 left: 15px;


 top: 15px;


}



.darkMode {


 background-color: black;


 transition: ease .3s;


}



.lightMode {


 background-color: #FFF;


 transition: ease .3s;


}



#darkModeSwitch input[type="checkbox"] {


 width: 40px;


 height: 20px;


 background: #fff89d;


}



#darkModeSwitch input:checked[type="checkbox"] {


 background: #757575;


}



#darkModeSwitch input[type="checkbox"]:before {


 width: 20px;


 height: 20px;


 background: #fff;


}



#darkModeSwitch input:checked[type="checkbox"]:before {


 background: #000;


}

<body id="body" class="lightMode">


 <div id="darkModeSwitch">


 <input type="checkbox" title="Toggle Light/Dark Mode" />


 </div>


</body>

保持简单。


 //Dark Mode


function darkMode() {


 body.className = currentBodyClass = (currentBodyClass==="lightMode") ?"darkMode":"lightMode";


}



如果你执行的不仅仅是一个""特性,那么只需交换类的定制函数就足够了。

...