前端工程师进阶要点一——各司其职(或职责分离)|小册免费学

298 阅读4分钟

前端体系知识划分:

  • 基础知识
    • 通用基础知识(数学、逻辑、算法、数据结构和设计模式以及语言基础知识等)
    • 专用基础知识(指HTML、CSS和JavaScript的基础)
  • 领域知识
    • 运行环境、工程化、框架和工具库以及细分领域

对于变化最快的领域知识,要以实用为出发点学习,掌握核心内容;专用和通用基础知识,需要深入学习,打好基础。

各司其职

  • HTML:网页的结构
  • CSS:网页元素的展示样式
  • JS:网页和用户的交互

2021-04-16-22-29-20.png

处理前端需求时,一定要遵循HTML、CSS、JS各司其职的原则,各自实现对应的功能,这样的好处不仅便于后续代码的维护扩展,而且可以做到代码简洁、可读性高。

HTML/CSS/JS职责实现举例

模式切换效果

比如一个深夜/白天模式切换的需求。点击"太阳🌞"图标,切换为深夜模式(深色背景、浅色字体、图标变为"月亮🌜")。

可以根据"图标"所在按钮,通过点击简单实现:

const btn = document.getElementById('modeBtn');
btn.addEventListener('click', (e) => {
  const body = document.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 = '🌞';
  }
});

这样效果就实现了。

但是,是否考虑了下面三点:

  1. 对于不了解需求的人,阅读这段代码是否可以直接理解"按钮"点击的含义?
  2. 如果需求变更,夜间模式改为深灰色背景、浅黄色文字,是否可以避免修改JS代码?
  3. 是否可以方便的添加切换过程的动画效果?

用class属性表示元素的业务状态

下面模式切换的js代码,直接阅读只知道是将background改为黑色、color改为白色。却不清楚该样式代表的业务需求或状态!

body.style.backgroundColor = 'black';
body.style.color = 'white';

这是因为,本该由CSS完成的工作交由JS来做了,应该由CSS设置元素的样式。

如下,重构代码体现出业务的需求:

  • CSS完成夜间模式样式
body.night {
  background-color: black;
  color: white;
}
  • JS代码重构为
const btn = document.getElementById('modeBtn');
btn.addEventListener('click', (e) => {
  const body = document.body;
  if(body.className !== 'night') {
    body.className = 'night';
    e.target.innerHTML = '🌜';
  } else {
    body.className = '';
    e.target.innerHTML = '🌞';
  }
});

这样修改的好处:

  • className通过语义化的night,描述了这是一个夜间(night)模式的业务状态,便于快速了解业务需求和后续维护。
  • 如果需求变更,修改模式的颜色。只需修改body.night的样式,不需要修改JS代码。
  • 如果增加切换的动画效果,可以使用CSS3实现,如:
body {
  padding: 10px;
  box-sizing: border-box;
  transition: all 1s;
}
body.night {
  background-color: black;
  color: white;
  transition: all 1s;
}

e.target.innerHTML = '🌜';的切换也可以改进为,合并到CSS中(伪元素实现):

#modeBtn::after {
  content: '🌞';
}
body.night #modeBtn::after {
  content: '🌜';
}

这样按钮#modeBtn的文本内容就可以清除,js代码也更简洁。

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

JS代码只负责切换元素的状态CSS改变元素的样式

最好的JS代码是没有JS代码(纯CSS实现状态切换)

如何只使用CSS实现“夜间模式”效果?核心是:使用CSS代替JS来切换并记住与用户交互的状态

在HTML中,能够完成状态切换的元素:复选框checkbox、单选框Radio、单选或多选选择列表select

通过input checkbox元素的普通状态选中状态,实现业务状态的切换:

<input id="modeCheckBox" type="checkbox">

如下,选中时的样式

/* 匹配checkbox选中状态下的.content */
#modeCheckBox:checked + .content {
  background-color: black;
  color: white;
  transition: all 1s;
}

此时,通过点击checkbox复选框实现模式的切换。

但是,还有个问题,无法通过点击🌞/🌜按钮实现状态切换,而且页面多出个复选框(点击复选框也是一个麻烦)。

可以借助for属性指定checkbox的id,比如label标签加for属性,实现点击label即点击表单元素,切换checkbox的状态,然后隐藏多出的checkbox。

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

隐藏checkbox:

#modeCheckBox {
  display: none;
}

从而实现只用CSS,不使用JS代码切换模式状态。

完整代码如下,同时修改了js部分的代码处理,可以适用当前的布局:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>深夜食堂</title>
    <style>
        body,
        html {
            width: 100%;
            height: 100%;
            padding: 0;
            margin: 0;
            overflow: hidden;
        }
        body {
            box-sizing: border-box;
        }
        .content {
            text-align: center;
            padding: 10px;
            transition: all 1s;
        }

        div.pic img {
            width: 60%;
        }
        #modeCheckBox {
            display: none;
        }
        #modeCheckBox:checked+.content,.content.night {
            background-color: black;
            color: white;
            transition: all 1s;
        }
        #modeBtn {
            font-size: 2rem;
            float: right;
        }
        #modeBtn::after {
            content: '🌞';
        }
        #modeCheckBox:checked+.content #modeBtn::after,.content.night #modeBtn::after{
            content: '🌜';
        }
    </style>
</head>
<body>
    <input id="modeCheckBox" type="checkbox">
    <div class="content">
        <header>
            <label id="modeBtn" for="modeCheckBox"></label>
            <h1>深夜食堂</h1>
        </header>
        <main>
            <div class="pic">
                <img src="https://p2.ssl.qhimg.com/t0120cc20854dc91c1e.jpg">
            </div>
            <div class="description">
                <p>
                    内容。。。
                </p>
            </div>
        </main>
    </div>
</body>
    <script>
        // const btn = document.getElementById('modeBtn');
        // btn.addEventListener('click', (e) => {
        //     const content = document.getElementsByClassName('content')[0];
        //     if (content.classList.contains('night')) {
        //         content.classList.remove('night');
        //     } else {
        //         content.classList.add('night');
        //     }
        // });
    </script>
</html>

2021-04-17-11-50-07.png

对比js版本和css版本

  • JS版本更加简洁,HTML结构更清晰简单。兼容性好一些。

  • CSS版本不用维护JS代码,尤其适用移动端。

唯一不会有bug的方式就是不写代码。所以,最好的JS代码就是没有JS代码

本文正在参与「掘金小册免费学啦!」活动, 点击查看活动详情