这是我参与「第四届青训营 」笔记创作活动的的第3天
写JS的一些原则
各司其职
让HTML、CSS、Javascript职能分离
组件封装
好的UI组件具备正确性、扩展性、复用性
过程抽象
应用函数式编程思维
三种JS写法的区别与优劣
用js控制css
用js控制类名
纯css控制页面变化
总结:
- HTML/CSS/JS各司其责
- 应当避免不必要的由JS直接操作样式
- 可以用class来表示状态
- 纯展示类交互寻求零JS方案
封装组件
组件是指Web页面上抽出来一个个包含模版(HTML)、功能(JS)和样式(CSS)的单元。好的组件具备封装性、正确性、扩展性、复用性。
制作轮播图
结构:HTML
轮播图是一个共型的列表结构,我们可以使用无序列表ul元素来实现。
CSS表现
- 使用CSS绝对定位将图片重叠在同一个位置
- 轮播图切换的状态使用修饰符(modifier)
- 轮播图的切换动画使用CSS transition
行为:API
Slider
- getSelectedItem() 得到当前选中的图片元素
- getselectedltemlndex() 得到当前选中图片元素列表下标
- slideTo() 到特定位置
- slideNext() 轮播下一张图片
- slidePrevious() 轮播上一张图片
JS行为
控制流,使用自定义事件来解释
总结:
- 结构设计
- 展现效果
- 行为设计 [ API(功能)+ Event(控制流)]
重构:插件化
解耦
- 将控制元素抽取成插件
- 插件与组件之间通过依赖注入方式建立联系
- 将HTML模板化,更易于扩展
1.做了插件抽象,将slide简化
抽象
将组件通用模型抽象出来
总结:
- 组件设计原则:封装性、正确性、扩展性、复用性
- 实现组件的步骤:结构设计、展现效果、行为设计
- 三次重构:插件化、模板化、抽象化(组件框架)
过程抽象
用来处理局部细节控制的一些方法
函数式编程思维的基础应用
e.g.:操作次数限制
一些异步交互,一次性http请求
怎么保证只执行一次:
function once(fn)//形成外部闭包outer scape closure
{
return function{...args}{//一个函数return另一个函数,称该函数为高阶函数。inner scope
if(fn){
//第一次调用时fn有值,会有返回值
const ret=fn.apply(this,args);
//调用函数,return
fn=null;
//之后fn变为null,不会有返回值,保证once返回方法只有一次
return ret;
}
}
}
//抽象一个once的过程,使参数为函数,使这个函数里的任何一个函数只被调用一次。为了能够让"只执行一次"的需求覆盖不同的事件处理,我们可以将这个需求剥离出来。这个过程我们称为过程抽象。
高阶函数HOF
- 以函数作为参数
- 以函数作为返回值
- 常用于作为函数装饰器
等价函数
常用高阶函数
- Once
- Throttle节流函数(鼠标移动moucemove事件,窗口滚动scroll事件)——事件触发多,带来相应的性能开销
- Debounce防抖(自动保存)
- Consumer/2
- Iterative可迭代方法(Jquery
节流函数
防抖
function debounce(fn, dur){
dur = dur || 100;
var timer;
return function(){
//频繁调用的时候会清空timer
clearTimeout(timer);
//只有停止的时候才会调用
tiner = setTimeout(()=>fn.apply(
this,arguments),dur);
}
}
consumer
consumer
可迭代方法
function iterative(fn){
return function(subjoct,...rest){
if(isIterable(subjet)){
//判断subject是否可迭代
const ret=[];
for(let obj of subject){
//用subject里的每个函数调用fn方法
ret.push(fn.applyithis,[obj, ...rest]);
}
return ret;
}
return fn.applyithis,[subject, ...rest]);
//不可迭代只调用一次
}
}
//有了iterative函数能操作多个元素进行函数
纯函数与非纯函数
非纯函数,会改变外部状态,需要构造特定环境,测试难度高,越多可度容信息差
使用高阶函数可以减少使用非纯函数
编程范式
命令式
声明式
三态
命令式
声明式
//命令式代码
switcher.onclick = function(evt){
if(evt.target.className === 'on'){
evt.target.className = 'off';
}else{
evt.target.className= 'on';
}
}
//声明式实现
function toggle(...actions){//接收一系列actins
return function(...args){
let action =actions.shift();
//取出第一个action放到最后一个
actions.push(action);
return action. apply(this, args);
//调用当前取出的action
}
}
switcher.onclick= toggle(
evt =>evt.target.className = 'off',
evt=>evt.target.className = 'on'
);
//在实现多个状态时,命令式需要添加多个逻辑代码,在声明式中只需要改个状态
总结:
- 过程抽象/ HOF/装饰器
- 命令式/声明式