JavaScript(一)| 青训营笔记

66 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 3 天

Day03——JavaScript(一)

写好JS的一些原则:各司其职、组件封装、过程抽象

各司其职

案例:给一个网页实现一个深色系和浅色系主题的切换,以使得在夜晚访问这个网页的读者能够使用“夜间模式”。

版本一:

以上这段代码给按钮注册了click事件,当用户点击按钮的时候,如果当前按钮文字是“太阳”,说明要从日间模式转换为夜间模式,那么将 body 的背景样式转换成深色,文字样式转换成浅色,否则将 body 的背景颜色转换为浅色,文字样式转换为深色。

缺点 ——在Javascript里直接操作了CSS代码,本该由 CSS 完成的工作交由 JS 来做了,本来应该由 CSS 设置元素的样式,却让 JS 代替了。(违背了JavaScript中各司其职的原则)

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

版本二:

当body元素的className属性不等于night时,表示(点击前)当前元素的状态是白天模式,所以现在需要将它的状态修改为夜间模式,于是我们只要将它的className属性设置为night,页面就会呈现夜间模式的样式。同理,当body元素的className属性等于night时,表示(点击前)body元素是夜间模式,所以需要将这个元素的状态修改为白天模式,也就是默认状态,即className属性等于空。

优点 ——操作的是className来控制HTML的状态(符合了JavaScript中各司其职的原则)

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

版本三:

纯CSS版本.

我们在 body 的子元素中添加一个type="checkbox"的input元素。当我们点击这个元素时,就有两种状态:普通状态和选中状态。其中,选中状态可以用伪类选择器#modeCheckBox:checked来标记。

由于元素是 body 的第一个子元素,它后面的子元素可以通过 CSS 的兄弟节点选择器来命中。为了便于统一操作,我们给 header 和 main 元素外层增加一个

的容器,这样我们就可以通过 CSS 选择器改变这个容器的样式:

#modeCheckBox:checked + .content :

这条规则表示当checkbox选中状态下,.content元素的样式为黑底白字。

所以:当 checkbox 被选中时,页面进入夜间模式;当 checkbox 不被选中时,页面又进入白天模式。

当然,这个效果和需求还有一定差距 —— 不能让用户点击页面顶部的 checkbox 来替代点击右上角太阳图标,这不符合业务需求。于是,我们打算使用 label 元素代替 checkbox 触发用户的点击行为。

<label id="modeBtn" for="modeCheckBox"></label>

通过 label 元素的 for 属性指定的 id,能够将 label 元素与对应的表单元素绑定,这样当用户点击 label 元素的时候,就相当于直接点击对应的表单元素。我们将原来的button元素用label元素代替,并将label元素的for属性指向checkboxid(modeCheckBox)这样就能够让label元素绑定checkbox元素。

优点:这样,我们就完美地实现了只用 CSS,不使用 JS 代码实现的“夜间模式”切换。

<style>
  #modeCheckBox {
    display: none;
  }
  #modeCheckBox:checked + .content {
    background-color: black;
    color: white;
    transition: all 1s;
  }

</style>
<body>
  <input id="modeCheckBox" type="checkbox" />
  <div class="content">
    <header>
      <label id="modeBtn" for="modeCheckBox"></label>
      <h1>深夜食堂</h1>
    </header>
    <main>
      ...
    </main>
  </div>
</body>

总结

  • HTML/CSS/JS各司其责
  • 应当避免不必要的由JS直接操作样式
  • 可以用class来表示状态
  • 纯展示类交互寻求零JS方案

tips:最好的 JS 代码就是没有 JS 代码