这是我参与「第五届青训营 」伴学笔记创作活动的第 3 天
基本原则
- 各司其职 - 保证 HTML、CSS、JavaScript 职能分离
- 组件封装 - 正确性、扩展性、复用性
- 过程抽象 - 函数式编程思想
各司其职 - 浅色主题和深色主题切换
利用JS直接修改页面整体样式 style 属性
利用JS修改页面级元素 class 类属性
利用checkbox伪类状态结合选择器实现
建议
- HTML、CSS、JavaScript各司其职
- 避免直接用JS操作样式
- 使用class来表示状态
- 纯展示类交互尽量减少JS的使用,寻求零JS方案
组件封装 - 轮播图
html结构 ul-li 即使用无序列表设置样式 css 样式,支持自动播放 js 支持点击跳转 (触发自定义事件,并监听自定义事件)
基本方法
- 结构设计
- 展现效果
- 行为设计
- API 功能
- Event 控制流
解耦-插件化
控制元素抽取成插件 插件与组件之间通过依赖注入的方式
解耦-模板化
将 HTML 模板化,更易于扩展
抽象化
将通用的组件模型抽象化,即形成组件框架
设计原则
封装性、正确性、扩展性、复用性
实现组件步骤
结构设计、展现效果、行为设计
过程抽象
黑箱思想
利用函数式编程方法
高阶函数 HOF
- 以函数为参数
- 以函数为返回值
- 常作为函数装饰器
function HOF (fn) {
return function (...args) {
return fn.apply(this, args)
}
}
function Once (fn) {
return function (...args) {
if (fn) {
const ret = fn.apply(this, ...args)
ret = null
return ret
}
}
}
function Throttle (fn, time = 1000) {
let timer = null
return function (...args) {
if (timer === null) {
fn.apply(this, args)
timer = setTimeout(() => {
timer = null
}, time)
}
}
}
function Debounce (fn, dur = 1000) {
let timer = null
return function () {
clearTimeout(timer)
timer = setTimeout(() => {
fn.apply(this, arguments)
}, dur)
}
}
function Consumer (fn, time) {
let tasks = []
let timer = null
return function (...args) {
tasks.push(fn.bind(this, ...args))
if (timer === null) {
timer = setInterval(() => {
tasks.shift().call(this)
if (tasks.length <= 0) {
clearInterval(timer)
timer = null
}
}, time)
}
}
}
function Iterative (fn) {
const isIterable = obj => obj != null && typeof obj[Symbol.iterator] === 'function'
return function (subject, ...rest) {
if (isIterable(subject)) {
const ret = []
for (const obj of subject) {
ret.push(fn.apply(this, [obj, ...rest]))
}
return ret
}
return fn.apply(this, [subject, ...rest])
}
}
纯函数
- 不应修改程序的状态或引起副作用,不影响外部变量
- 不使用外部变量,即自包含
- 函数输出仅与函数输入有关,其对任一给定的输入有唯一确定的输出
编程范式
命令式 imperative
switcher.onclick = function(evt){
if(evt.target.className === 'on'){
evt.target.className = 'off'
}else{
evt.target.className = 'on'
}
}
声明式 declarative
function toggle(...actions){
return function(...args){
let action = actions.shift()
actions.push(action)
return action.apply(this, args)
}
}
switcher.onclick = toggle(
evt => evt.target.className = 'off',
evt => evt.target.className = 'on',
)