各司其职

各司其职

让 HTML、CSS和 JavaScript 职能分离,HTML是页面的骨架,CSS是页面的皮肤,JavaScript是页面的动作了。我们在写代码的时候应该他们各自负责自己该负责的部分,尽可能的少用 JS 干扰 CSS 和 HTML ,这样的代码才是高质量的。

例子:深色模式切换

实现效果如下:

image.png

当点击了🌞之后变为:

image.png

为了对比代码的优劣,下面给出了三种版本的代码做分析

  • 版本一
//html
 <header>
        <button id="modeBtn">🌞</button> //给按钮绑定鼠标点击事件
        <h1>深浅色模式切换</h1>
 </header>
 
 //css
 body,
    html {
      width: 100%;
      height: 100%;
      padding: 0;
      margin: 0;
      overflow: hidden;
    }

    body {
      padding: 10px;
      box-sizing: border-box;
    }

    #modeBtn {
      font-size: 2rem;
      float: right;
      border: none;
      background: transparent;
    }

//js
window.onload=function(){
    document.getElementById("file-btn") 
    const btn = document.getElementById('modeBtn');

    btn.addEventListener('click', (e) => {
      const body = document.body; //获取页面body元素
      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中操作了body的style,修改了元素的样式和结构,显得结构混乱,这样的写法明显不符合我们的各司其职的原则!

我们的代码不仅要写给自己看,更是要写给队友看,于是经过优化,我们写出了下面的版本二 ↓

  • 版本二
//html
 <header>
        <button id="modeBtn"></button> //给按钮绑定鼠标点击事件,与版本一不同的是去掉了🌞
        <h1>深浅色模式切换</h1>
 </header>
 
 //css
body,
    html {
      width: 100%;
      height: 100%;
      max-width: 600px;
      padding: 0;
      margin: 0;
      overflow: hidden;
    }

    body {
      padding: 10px;
      box-sizing: border-box;
      transition: all 1s;
    }

    #modeBtn {
      font-size: 2rem;
      float: right;
      border: none;
      outline: none;
      cursor: pointer;
      background: inherit;
    }

    body.night {
      background-color: black;
      color: white;
      transition: all 1s; //美观上做了一些调整,切换时有1秒的延时
    }

    #modeBtn::after { //各司其职,让css来实现图标的切换
      content: '🌞';
    }

    body.night #modeBtn::after {
      content: '🌜';
    }
    
//js
window.onload=function(){
    document.getElementById("file-btn") 
   const btn = document.getElementById('modeBtn');
        btn.addEventListener('click', (e) => {
        const body = document.body;
        if (body.className !== 'night') { //通过className的'night'来显示深色模式,判断上更直观
            body.className = 'night';
        } else {
            body.className = '';
        }
        });
}

 

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

好处一

版本二中的 js 仅仅是修改元素的类名className,描述了这是一个深色(night)模式的状态,这样就便于别人快速理解业务需求,能更直观的表达代码想表达的意思,可读性也提高了。

好处二

可以更灵活变更背景等样式需求。如果需求变更,例如把模式对应的颜色换了,我们不需要修改 JS 代码,只需要修改body.night的样式规则即可

但是,是否还有更优化的方案呢?版本三的优化甚至不需要写 js !我们来看看

  • 版本三
//html
<input id="modeCheckBox" type="checkbox"> //通过点击,记住勾选和不勾选的两个状态,刚好对应浅色模式和深色模式两种状态
  <div class="content">
    <header>
      <label id="modeBtn" for="modeCheckBox"></label>
      <h1>深浅色模式切换</h1>
    </header>
  </div>
  
//css
body,
    html {
      width: 100%;
      height: 100%;
      padding: 0;
      margin: 0;
      overflow: hidden;
    }

    body {
      box-sizing: border-box;
    }

    .content {
      padding: 10px;
      transition: background-color 1s, color 1s;
    }

    #modeCheckBox {
      display: none; //将大盒子外面的checkbox隐藏起来
    }

    #modeCheckBox:checked+.content { //通过 checkbox 的伪类选择器checked,点击checkbox就会触发这个伪类
      background-color: black;
      color: white;
      transition: all 1s;
    }

    #modeBtn {
      font-size: 2rem;
      float: right;
    }

    #modeBtn::after {
      content: '🌞';
    }

    #modeCheckBox:checked+.content #modeBtn::after {
      content: '🌜';
    }

注意:+ 介于两个选择器之间,当第二个元素紧跟在第一个元素之后,并且两个元素都是属于同一个父元素的子元素,则第二个元素将被选中

版本三中,我们通过 CSS 来完成了本来应该 JS 完成的切换模式并记住状态的功能。我们让选中状态用伪类选择器#modeCheckBox:checked来标记

结论:

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

 

posted @ 2022-07-29 23:21  grigeorge  阅读(87)  评论(0编辑  收藏  举报