这是我参与「第五届青训营 」伴学笔记创作活动的第 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 元素外层增加一个
#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属性指向checkbox的id(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 代码