这是我参与「第四届青训营 」笔记创作活动的第24天,也是课程结束后的第一天,本篇将对在青训营里学到的javascript相关内容进行一个总结。
深夜食堂
结论:
- html、css、js各司其职
- 避免不必要的由js直接操作
- class可用来表示状态
- 纯展示类交互寻求零js方案
组件封装
组件:web页面上拖出来的一个个包含模板(html)、功能(js)、样式(css)的单元
好的组件特性: 封装性、正确性、扩展性、复用性
案例教学
轮播图
行为: API: getSelectedItem() getSelectedItemIndex() slideTo() slideNext() slidePrevious()
基本方法
- 结构设计
- 展现效果
- 行为设计 API(功能) Event(控制流):自定义事件解耦
重构:插件化
原先组件功能没问题,但是不够灵活:不能更改控件... 改进:重构,插件化组件
原先代码大多在construcrtor里,不好
开发自定义事件:
-
定义事件数据 const detail = {index : idx} //index为名称
-
创建事件 const myEvent = new CustomEvent('事件名称', {可配置项}) 可配置项:事件冒泡bubbles:true , 传递参数detail
-
添加事件监听 .addEventListener('事件名称',e=>{ (e.detail.index 调用参数) 事件; })
-
派发事件 .dispatchEvent(myEvent)
//创建
const detail = {index: idx}
const event = new CustomEvent('slide', {bubbles:true, detail})
this.container.dispatchEvent(event)
//
addEventListener(type, handler){
this.container.addEventListener(type, handler)
}
//事件监听
slider.addEventListener('slide', evt => {
const idx = evt.detail.index;
const selected = controller.querySelector('.btn-control--selected');
if(selected) selected.className = 'btn-control';
buttons[idx].className = 'btn-control--selected';
});
解耦
-
将控制元件抽取成插件
-
插件与组件之间通过 依赖注入 方式建立联系
重构:模板化
将html模板化,易于扩展
组件封装-总结
-
组件设计原则: 封装性,正确性,扩展性,复用性
-
实现组件的步骤: 结构设计,展现效果,行为设计
-
三次重构 插件化 模板化 抽象化
过程抽象
处理局部细节控制的一些方法 函数式编程思想的基础应用
input x --> output f(x)click
只触发一次click addEventListener('click',()=>{},(once:true)) addEventListener('click', once( ()=>{ } ) ) 封装成一个过程抽象/高阶函数
function once(fn) {
//外部闭包
return function(...args){
if(fn){
const ret = fn.apply(this, args);
fn = null;
return ret;
}
}
}
高阶函数
函数作为参数 函数作为返回值 常用于做函数装饰器
//等价高阶函数
function HOF0(fn){
return function(...args){
return fn.apply(this, args);
}
}
常用高阶函数:
- once
- throttle节流函数
function throttle(fn, time = 500){
let timer ;
return function(...args){
if(timer == null){
fn.apply(this, args);
timer = setTimeout(() => {
timer = null;
}, time);
}
}
}
- debounce防抖 比如打字或者移动鼠标,不动了再进行保存
function debounce(fn, dur){
dur = dur || 100;
let timer;
return function(){
clearTimeout(timer);
timer = setTimeout(()=>{
fn.apply(this, arguments);
}, dur);
}
}
- consumer/2
- Iterative 可迭代方法,批量操作
const isTterable = obj => !=null && typeof obj[Symbol.iterative] === 'function';
function Iterative(fn){
return function(subject, ...rest){
const ret = [];
for(let obj of subject){
ret.push(fn.apply(this. [obj, ...rest]));
}
return ret;
}
return fn.apply(this, [subject, ...rest]);
}
为什么要使用高阶函数
编程范式
命令式与声明式
红绿灯:
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 = 'warn',
evt => evt.target.className = 'off',
evt => evt.target.className = 'on'
);