这是我参与「第五届青训营 」伴学笔记创作活动的第 2 天。
这一篇笔记记录了如何遵循工业化、规范化的编程原则写出更好的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基础。