这是我参与「第四届青训营 」笔记创作活动的第3天
Day3 JavaScript
JS三原则
- 各司其职 ,让HTML、CSS和JavaScript职能分离
- 组件封装 ,好的UI组件具备正确性、扩展性、复用性
- 过程抽象应用函数式编程思想
1. 各司其职
实例 深夜食堂-明暗模式切换
(1) Version1
没有做到各司其职,不利于维护修改
具体:用JS做了CSS的工作
const btn = document.getElementById("app_btn")
btn.addEventListener("click", (e) => {
const body = document.body
const DARK_MODE_ON = "Dark Mode On"
const DARK_MODE_OFF = "Dark Mode Off"
if(e.target.innerHTML === DARK_MODE_ON){
body.style.backgroundColor = 'black'; // 用JS做了CSS的工作
// ...
}else{
// ...
}
})
(2) Version2
职能分离
具体:通过指定类名来切换样式
if(body.className != 'night') {
body.className = 'night'; // 通过指定类名来切换样式
}
(3) Version3
纯CSS实现,通过使用伪类选择器来完成功能。
在HTML中:嵌入一个类型为checkbox的input标签,display: none;
在CSS中:指定一个状态性伪类+兄弟选择器,在checkbox的状态为checked的情况下,选中后面类名为content的组件修改样式,从而实现黑夜模式。
#mode-checkbox:checked + #app {
background-color: black;
color: white;
transition: all 1s; //通过CSS的transition属性实现一个简单的动画。
}
(4) 结论
HTMLCSSJavaScript应该各司其责- 应当尽量避免由JavaScript直接操作样式
- 可以寻求纯展示类交互,无JS
2. 组件封装
组件是指Web页面上抽出来的,包含模版(HTML)、功能(JS)和样式(CSS)的单元。
实例 轮播图
(1) Version1 设计
HTML
轮播图是一个典型的列表结构,可以用无序列表ul来表示
CSS
- 使用CSS的绝对定位将图片重叠在同一个位置
- 轮播图切换的状态使用修饰符
- 轮播图的切换动画可使用CSS 的
transition
JS
用类封装Slider组件,设计API
(2) Version2 插件化重构
Version1 不够灵活,因为修改一处,所有地方都要修改
插件与组件之间可以通过依赖注入的方式建立联系:
将控制插件依赖的Slider类实例注入到控制插件中,从而将控制插件与Slider类的实现,方便添加或去除控制插件
(3) Version3 模板化重构
将无序列表和图片直接写在HTML中。可以将HTML模板化,更易于扩展,做到数据驱动
(4) Version4 组件框架
可以考虑将组件和插件统一用一个类来实现,从而实现父插件、子插件的嵌套。
(5) 总结
- 组件设计的原则:正确性、扩展性、复用性
- 实现组件的步骤:结构设计、展现效果、行为设计
- 三次重构:插件化、模板化、抽象化
3. 过程抽象
过程抽象是用来处理局部细节控制的一些方法,是函数式编程思想的基础应用
实例 简单任务列表
存在的问题:连续点击,删除子元素 的代码被执行多次
解决的方法:利用高阶函数once多次调用只执行一次
function once(fn) {
return function(...args){
// 判断是否已经执行
if(fn){
// 如果没有执行,应用参数返回结果
const result = fn.apply(this, args);
// 把传入的fn设置为null,保证执行一次
fn = null;
return result;
}
}
}
其中,once函数是一个外部闭包,once函数返回的函数是一个内部闭包
高阶函数(HOF)
- 函数作为参数
- 函数作为返回值
- 常用于函数装饰器
编程范式
- 命令式:HOW to do
- 声明式:WHAT to do