「青训营」笔记创作活动的的第4天
JS 代码优化原则 - 各司其职
HTML 负责页面的框架,CSS 负责页面的展现,JavaScript 负责页面的行为。
案例:实现夜间模式的切换
版本一:JS 直接操作样式
const btn = document.getElementById("modeBtn");
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 不应当直接操作元素的样式
版本二:JS 切换类选择器
const btn = document.getElementById("modeBtn");
btn.addEventListener("click", (e) => {
const body = document.body;
if (body.className !== "night") {
body.className = "night";
} else {
body.className = "";
}
});
复制代码
优化:
- 太阳和月亮图标不是直接以文本形式写在按钮里面,而是通过::after 伪元素添加进去
- 通过类选择器给元素添加样式,再通过 js 控制类选择器
版本三:零 JS 代码实现
优点:
- 通过 label 标签绑定多选框,再通过多选框的:checked 伪类选择器控制样式的切换
- 零 JS 代码
- 易于后期维护
案例总结
- HTML/CSS/JS 各司其责
- 应当避免不必要的通过 JS 直接操作元素样式
- 可以用 class 来表示状态
- 纯展示类交互寻求零 JS 方案
JS 代码优化原则 - 组件封装
案例:实现一个轮播图
- 结构:HTML - 无序列表
<ul> - 表现:CSS
- 绝对定位将图片重叠在同一个位置
- 轮播图切换状态使用修饰符(modified)
- 动画切换使用 transition
- 行为:JS - API 设计应保证原子操作,职责单一,满足灵活性。行为设计:
优化:
重构 - 插件化: 解耦:
-
将控制元素抽取成插件
-
插件与组件之间通过依赖注入方式建立联系 补充:在JS中 一个对象方法或者一个函数尽量控制在15行代码以内。
版本三重构 - 模板化:更易于拓展,不需要的功能可以直接去掉而不影响其他功能
版本四重构 - 组件抽象框架:将通用的组件抽象出来
版本五
总结
组件是指Web页面上抽出来一个个包含模板(HTML)、功能(JS)、和样式(CSS)的单元;
组件设计的原则:封装性、正确性、拓展性、复用性;
实现组件的步骤:结构设计、展现效果、行为设计;
三次重构:插件化、模板化、抽象化。
JS 代码优化原则 - 过程抽象
过程抽象:
- 用来处理局部细节控制的一些方法
- 函数式编程思想的基础应用
例子 - 操作次数限制:
假如需要对某个函数的调用次数进行限制,我们可以直接在函数内进行控制,但是如果出现了多个同样需求的函数,则未免会写很多重复的的代码,此时我们可以通过一个高阶函数完成这个功能。
function once(fn){
return function (...args) {
if(fn){
const ret = fn.apply(this, args);
fn = null;
return ret;
}
};
}
复制代码
为了能够让“只执行一次”的需求覆盖不同的事件处理,我们可以将这个需求剥离出来。这个过程我们称为过程抽象。
高阶函数
- 以函数作为参数 或者 以函数作为返回值
- 常用于作为函数装饰器
常用的高阶函数:
为什么要使用高阶函数?
函数可以分为纯函数和非纯函数。
纯函数:在任何时候以相同的参数调用它,输出是相同的,即不依赖于外部环境。
非纯函数:非纯函数依赖外部环境(或者说是调用时机),当使用相同的参数在不同的外部环境调用时,函数输出的结果果也会不同。
因为非纯函数很难保证每次调用时都有相同的外部环境,所以使用纯函数更有助于后期的单元测试。并且使用纯函数可以使得系统更加稳定。
编程范式
- 命令式:过程式、面向对象
- 声明式:逻辑式、函数式
JS 是混合的编程方式,既可以写出命令式风格的代码,也可以写出声明式风格的代码。
例子 - 切换状态