这是我参与「第五届青训营」笔记创作活动的第6天。这里记录下JS阶段学到的优化原则——让HTML、CSS、JS各司其职。
一、本堂课重点内容:
各司其职:让HTML、CSS和 Javascript 职能分离。
二、详细知识点介绍:
首先,我们来看这样一个需求:如果需要给一个写好框架和基本样式的页面添加“白天/夜间”模式的切换,我们以什么样的方式去实现这一需求呢?
最基本的方法便是在JS中完成对于样式的操控:
const btn = document.getElementById('modeBtbtn')
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 = '🌞';
}
});
这个大概是JS初学者的选择,在页面元素不复杂(比如说基本都是文字+背景)时,这样做是比较快捷的方式。当然,在做了一些项目之后,我现在更倾向于在在CSS中新增类选择器(如.dark)然后利用选择器在对应位置编写两套CSS样式,在JS中仅仅完成类名的添加、删除。
const btn = document.getElementById('modeBtbtn')
btn.addEventListener('click',(e) => {
const body = document.body;
if(body.className !== 'night'){
body.className = 'night';
} else {
body.className = '';
}
});
不言而喻,这两种方式中,后一种是更好的实现方式。这种方式下,可以很方便的通过CSS的transition属性进行过渡效果。CSS和 JS 耦合度降低,而且后续维护或者修改“深夜模式”的样式时更加方便,在CSS中类名见名知义,很容易知道哪些样式是在暗黑模式下的。不过第二种方式依然是通过 JS 去操控了页面样式。
这里老师提供了一种思路:增加一个 display: none; 属性的 checkbox,利用CSS的checked属性来实现主体内容的风格切换。然后将原来页面中触发风格切换的 button 改为 label,将label的for属性和多选框的id保持一致,这样就实现了 点击 label 等同于点击看不见的 checkbox,从而触发 checked 状态。通过这种方式实现不需要写相关的 JS 代码,仅仅依靠新增的HTML结构和CSS代码就可以完成需求。
关键的HTML代码如下:
<input id="modeCheckBox" type="checkbox"/>
...
<label id="modeBtn" for="modeCheckBox"></label>
一些关键的CSS代码如下:
.content {
height: 100%;
padding: 10px;
transition: background-color 1s, color 1s;
}
#modeCheckBox {
display: none;
}
#modeCheckBox:checked + .content {
background-color: black;
color: white;
transition: all 1s;
}
#modeBtn {
font-size: 2rem;
float: right;
}
#modeBtn::after {
content: '🌞';
}
#modeCheckBox:checked + .content #modeBtn::after {
content: '🌜';
}
完整的代码仓库参见:青训营-深夜食堂-3 - 码上掘金 (juejin.cn)
这种方式确实是我没有见过的,不得不说为我提供了新的设计思路。和在定制化文件上传窗口时,隐藏掉 input 框改用 label 索引有异曲同工之妙。
实事求是地讲,尽管职能分离是前端工程师应该追求的方向之一,但是过度的追求三件套不耦合私以为反而增加了维护成本或者降低了可读性。在本例中,尽管实质上第三种和第二种方式在CSS样式上代码量几乎一致,但是明显第二种有更好的可读性,语义化更强。并且不需要太过考虑选择器优先级的问题,因为只需要用 .dark.[原来的类名]就可以完成暗黑模式下的对应。像第三种方式明显臃肿很多。而且,第三种方式确实实现了解耦合,但是稍微破坏了原有的DOM结构,而且相比第二种方式,两者在后续维护的时候其实都是只需要更改CSS部分即可,第二种方式的JS代码逻辑简单,根本不需要修改。因此我认为第三种方式并不实用。
三、实践练习例子:
事实上,在大部分含有“白天/黑夜”模式切换的网页,基本都是通过增加/删去类名来实现的,比如说vue、vueuse、react等的官方文档。打开控制台以后都可以看到类名的变化。
四、课后个人总结:
本章的知识点需要大量的实例和参考资料来辅助理解。
五、引用参考:
我主要是基于老师讲解提供的代码仓库进行理解和分析,并记录了自己的心得。