【青训营】写好JS——各司其责

简介: 【青训营】写好JS——各司其责

image.png


我们要明白:把CSS,JS放到单文件中这种代码层面的分离并不是各司其责,各司其责要做到职责的分离,比如我们要尽可能避免JS直接操作样式。


例子:Dark Mode



用JS实现浅色模式和深色模式的切换,如果是你,你会怎么做?


学成归来版


学完月影大大的JS课,复刻了一个常见的Dark Mode切换方式当作业,想看代码可以点这里,如果想知道怎么做,就继续往下看吧!


第一版


我们先写一段示例用的HTML:


image.png


新手可能会这样写JS来切换模式:


const btn = document.getElementById('modeBtn');
const body = document.body;
btn.addEventListener('click', (e) => {
  if(e.target.innerHTML === '🌞') {
    body.style.backgroundColor = 'black';
    body.style.color = 'white';
    e.target.innerHTML = '🌜';
  } else {
    body.style.backgroundColor = 'white';
    body.style.color = 'black';
    e.target.innerHTML = '🌞';
  }
});
复制代码


这样写看似逻辑很清晰,但是JS代码直接操作了HTML和CSS,显然没有做到各司其责,而且代码可读性不是很好,第一时间并不能让人分辨出这是切换深色模式的代码。


第二版


第二版我们先在CSS里封装一个深色类,通过::after伪类添加HTML内容:


.night {
  background-color: black;
  color: white;
  transition: all 1s;
}
#modeBtn::after {
  content: '🌞';
}
.night #modeBtn::after {
  content: '🌜';
}
复制代码

然后JS只用添加或者删除类名就可以实现样式切换,这也是我常用的方法:


const btn = document.getElementById('modeBtn');
btn.addEventListener('click', (e) => {
  const body = document.body;
  if (body.className !== 'night') {
    body.className = 'night';
  } else {
    body.className = '';
  }
});
复制代码

也可以用toggle()简化一下,关于该函数的用法可以看MDN文档


const btn = document.getElementById("modeBtn");
btn.addEventListener("click", (e) => {
  document.body.classList.toggle("night");
});
复制代码


这样写没有直接操作页面样式,JS只需要修改元素的类名即可,同时类名night又能让人很容易分辨出代码的用途,但这就是最好的解决方案了吗?月影大大告诉你,并没有,我们还有最终版!


最终版


只要我不写代码,就永远不会有Bug!


我们先来思考一个问题,既然我们只是单纯的展示页面,我们能不能不用JS呢?单纯的CSS能不能实现这个切换功能呢?答案是当然可以。


CSS中checkbox复选框就有checked选中和未选中两种状态,正好可以用来实现状态的切换。我们把复选框隐藏,然后用label显示🌞🌜:


<input id="modeCheckBox" type="checkbox">
<div class="content">
  ...
  <label id="modeBtn" for="modeCheckBox"></label>
  ...
</div>
<style>
  #modeCheckBox {
    display: none;
  }
  #modeCheckBox:checked + .content {
    background-color: black;
    color: white;
    transition: all 1s;
  }
  #modeBtn::after {
    content: '🌞';
  }
  #modeCheckBox:checked + .content #modeBtn::after {
    content: '🌜';
  }
</style>
复制代码


重剑无锋,大巧不工。我们应该做到:


  1. HTML/CSS/JS 各司其责
  2. 避免不必要的由JS直接操作样式
  3. 用class来表示状态
  4. 纯展示类的页面交互寻求零JS方案
目录
相关文章
|
存储 缓存 自然语言处理
深入理解JS | 青训营笔记
深入理解JS | 青训营笔记
97 0
|
数据采集 缓存 负载均衡
【青训营】-🥝Node.js基础入门
【青训营】-🥝Node.js基础入门
227 3
【青训营】-🥝Node.js基础入门
|
监控 JavaScript 前端开发
Node.js入门 | 青训营
Node.js入门 | 青训营
208 0
Node.js入门 | 青训营
|
算法 JavaScript
【青训营】写好JS——保证正确
【青训营】写好JS——保证正确
125 0
【青训营】写好JS——保证正确
|
算法 JavaScript
【青训营】写好JS——学好算法
【青训营】写好JS——学好算法
143 0
【青训营】写好JS——学好算法
|
JavaScript 前端开发
【青训营】写好JS——做好抽象
【青训营】写好JS——做好抽象
184 0
【青训营】写好JS——做好抽象
|
JavaScript
【青训营】写好JS——写代码最应该关注什么?
【青训营】写好JS——写代码最应该关注什么?
157 0
【青训营】写好JS——写代码最应该关注什么?
|
JavaScript 测试技术
【青训营】写好JS——过程抽象
【青训营】写好JS——过程抽象
336 0
【青训营】写好JS——过程抽象
|
JavaScript 前端开发 API
【青训营】写好JS——组件封装(下)
【青训营】写好JS——组件封装(下)
329 0
【青训营】写好JS——组件封装(下)
|
JavaScript 前端开发 API
【青训营】写好JS——组件封装(上)
【青训营】写好JS——组件封装(上)
290 0
【青训营】写好JS——组件封装(上)