各司其职
各司其职
让 HTML、CSS和 JavaScript 职能分离,HTML是页面的骨架,CSS是页面的皮肤,JavaScript是页面的动作了。我们在写代码的时候应该他们各自负责自己该负责的部分,尽可能的少用 JS 干扰 CSS 和 HTML ,这样的代码才是高质量的。
例子:深色模式切换
实现效果如下:
当点击了🌞之后变为:
为了对比代码的优劣,下面给出了三种版本的代码做分析
- 版本一
//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 方案