这一篇笔记记录了如何遵循工业化、规范化的编程原则写出更好的JS代码。
一、本堂课重点内容
- JavaScript 编码原则之各司其责
- JavaScript 编码原则之组件封装
- JavaScript 编码原则之过程抽象
二、详细知识点介绍
1、JavaScript 编码原则之各司其责
- 在编写项目的时候,HTML、CSS、JavaScript尽量各做各该做的事情,HTML就负责页面结构,CSS就负责样式渲染,JavaScript就负责交互行为。
- 在课程中,月影老师从一个切换日间与夜间风格的需求入手,逐步讲解如何一步一步地优化代码,直到达到“各司其责”的目的。
- 借用YK菌的一句话:“最好的JS就是不写JS”,秉承着这样的理念,我尝试使用纯CSS写了一个包含焦点的轮播图
轮播图设计
- 页面结构
- 三个
radio
按钮和对应的label
作为轮播图焦点
<div id="carousel"> <ul> <input type="radio" name="control" checked /> <input type="radio" name="control" /> <input type="radio" name="control" /> <li class="image"><img src="..." alt="" /></li> <li class="image"><img src="..." alt="" /></li> <li class="image"><img src="..." alt="" /></li> <div class="bottom-button"> <label for="control-1"></label> <label for="control-2"></label> <label for="control-3"></label> </div> </ul> </div>
- 三个
- 基础样式
- 隐藏
radio
单选框 - 焦点框使用绝对定位,固定到轮播图的底端位置,内部元素居中对齐。
- 焦点设置长宽、背景颜色,通过设置
border-radius
使其变为圆形。 - 设置焦点的悬停样式,通过
:checked
伪类选择器和~兄弟选择器找到被选中的焦点对应的label
并修改其样式。
#carousel input[type="radio"] { display: none; } #carousel .bottom-button { position: absolute; top: calc(100% - 50px); left: 0; width: 100%; height: 50px; display: flex; justify-content: center; align-items: center; } .bottom-button label { width: 10px; height: 10px; border-radius: 50%; background-color: rgba(255, 255, 255, 0.575); margin: 0 5px; cursor: pointer; transition: all 0.3s; } .bottom-button label:hover { box-shadow: #fff 0 0 5px; background-color: #fff; } #carousel input[type="radio"]:nth-of-type(1):checked ~ .bottom-button label:nth-child(1), #carousel input[type="radio"]:nth-of-type(2):checked ~ .bottom-button label:nth-child(2), #carousel input[type="radio"]:nth-of-type(3):checked ~ .bottom-button label:nth-child(3) { background-color: #fff; }
- 隐藏
- 轮播变换
- 通过
:checked
伪类选择器和~兄弟选择器找到被选中的焦点对应的图片并修改其opacity
透明度样式,达到轮播的效果。 - 当然这里只实现了手动轮播的效果,没有实现自动轮播的效果。
#carousel input[type="radio"]:checked ~ li.image { opacity: 0; } #carousel input[type="radio"]:nth-of-type(1):checked ~ li.image:nth-of-type(1), #carousel input[type="radio"]:nth-of-type(2):checked ~ li.image:nth-of-type(2), #carousel input[type="radio"]:nth-of-type(3):checked ~ li.image:nth-of-type(3) { opacity: 1; }
- 通过
- 进一步思考
- 一般的轮播图除了焦点之外通常还会有左右两个按钮,有一个实现的方案是添加多个左右切换的按钮,并设置不同的
label
对应不同的焦点,然后随着切换改变display
值。但是这个方法随着轮播图片的增加而变得繁琐。我还没有想到什么很好的纯CSS实现方法,因此使用js实现。 - 设置一个当前播放的图片的序号值
cur
,获取图片数量,然后给左右按钮各绑定一个事件,当点击时当前图片的前/后一张图片所对应的radio
设置为checked
。 - 在实现了左右切换后,该轮播图还未实现自动轮播的效果。个人认为如果要实现自动轮播的效果,则需要添加更多的js代码以及修改页面html和css样式。
/* 省略页面结构和CSS样式 */ const leftArrow = document.querySelector(".left-arrow"); const rightArrow = document.querySelector(".right-arrow"); const control = document.querySelectorAll('input[name="control"]'); const image = document.querySelectorAll(".image"); let cur = 0; let imageNum = image.length; leftArrow.addEventListener("click", () => { cur = (cur + imageNum - 1) % imageNum; control[cur].checked = true; }); rightArrow.addEventListener("click", () => { cur = (cur + 1) % imageNum; control[cur].checked = true; });
- 一般的轮播图除了焦点之外通常还会有左右两个按钮,有一个实现的方案是添加多个左右切换的按钮,并设置不同的
2、JavaScript 编码原则之组件封装
组件是指Web页面上抽出来的一个个包含模板(HTML)、功能(JS)和样式(CSS)的单元。好的组件具备封装性、正确性、扩展性、复用性。
- 组件封装的基本方法
- 结构设计
- 展现效果
- 行为设计
- API(功能)
- Event(控制流)
- 三次重构
- 插件化
- 模板化
- 抽象化
- 本节老师所使用的例子也是轮播图,后期可以参考老师的代码,在前一节的基础上进行改进。
3、JavaScript 编码原则之过程抽象
- 过程抽象能够体现出一定的函数式编程的思想,它能够用来处理一些局部细节的控制
- 高阶函数
- 以函数作为参数
- 返回值为函数
- 常用于作为函数装饰器
- 编程范式(声明式更简洁、更具有表现力,因此推荐使用声明式编程)
- 命令式
function addOne(arr) { const result = []; for(let i = 0; i < arr.length; i++) { result.push(arr[i] + 1) } return result; }
- 声明式
const addOne = arr => arr.map(item => item + 1);
三、实践练习例子
- 代码已在详细内容介绍中给出
四、课后个人总结
- 本章内容偏高阶,需要有很扎实的JavaScript基础,课后需要加强巩固JavaScript基础。