360前端星计划学习笔记day2
1. 各司其职
css和js功能分离
2. 复杂UI组件的设计
例子:实现一个轮播图
步骤一:结构设计
基本结构(使用bem命名规范)
<div id="my-slider" class="slider-list">
<ul>
<li class="slider-list__item--selected">
<img src=""/>
</li>
<li class="slider-list__item">
<img src=""/>
</li>
<li class="slider-list__item">
<img src=""/>
</li>
<li class="slider-list__item">
<img src=""/>
</li>
</ul>
<div>
- 图片结构是列表型结构,使用
<ul> - 使用css绝对定位将图片重叠在同一个位置
- 轮播图切换的状态使用修饰符(modifier)
- 轮播图的切换动画用css transition
控制结构: 左右和下面小圆点按钮
<a class="slide-list__next"></a>
<a class="slide-list__previous"></a>
<div class="slide-list__control">
<span class="slide-list__control-buttons--selected"></span>
<span class="slide-list__control-buttons"></span>
<span class="slide-list__control-buttons"></span>
<span class="slide-list__control-buttons"></span>
</div>
步骤二 API设计
- getSelectedItem()
- getSelectedItemIndex() 鼠标到下面小圆点
- slideTo()
- slideNext() 上一个
- slidePrevious() 下一个
- setInterval() 做切换
- 自定义事件:激活小圆点的状态,图片切换时候小圆点对应切换
- stop() 停止定时器
- start() 打开定时器
改进
- 小圆点和左右按钮使用插件,
plugin(this)依赖注入,降低耦合度 - 模版化:把html代码整合在js中,只需要维护一处地方,在
render()中设置html的内容
组件是数据和行为驱动的,结构交给组件内部机制生成 - 组件模型抽象:通用抽象类
Component可以用来扩展其他组件,在这个组件中注册插件,渲染data,Slider组件继承Component,从而形成一个UI组件库雏形
3. 局部细节控制
只允许执行一次
addEventListener设置onceonclick调用一次以后设置block.onclick = null
很多操作都需要只执行一次-->统一抽象 -->高阶函数
自身输入是一个函数,或者返回值是函数,被称为高阶函数
过程抽象:
function once(fn){
return function(...args){
if(fn){
let ret = fn.apply(this,args);
fn = null;
return ret;
}
}
}
节流:用于scroll或者mousemove这种执行次数比较多的执行函数
function throttle(fn,time=500){
let timer;
return function(...args){
if(timer == null){
fn.apply(this,args);
timer = setTimeout(()=>{
timer = null;
},time)
}
}
}
防抖:只需要得到用户最终状态的情况
function debounce(fn,dur){
dur = dur || 100;
var timer;
return function(){
clearTimeout(timer);
timer = setTimeout(()=>{
fn.apply(this,arguments);
},dur);
}
}
消费者:每次执行的时候push到任务队列里,每隔多长时间执行一次,把同步执行操作变为异步执行操作。使用consumer可以实现连击事件。
function consumer(fn,time){
let tasks = [],
timer;
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 consumerAdd = consumer(add,1000);
声明式编程和指令式编程
- 声明:关注做什么
- 指令:关注怎么做
iterative
多个reduce实现通用性
function iterative(fn){
return function(...args){
return args.reduce(fn.bind(this));
}
}
const add = iterative((x,y)=>x+y);
const sub = iterative((x,y)=>x-y);
声明式的toggle
具有更好的通用性
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',
evt => evt.target.className = 'warn',
)
使用生成器
function * loop(list,max=Infinity){
let i = 0;
while(i<max){
yield list[i++ % list.length];
}
}
function toggle(...actions){
let action = loop(actions);
return function(...args){
return action.next().value.apply(this,args);
}
}
总结
- 各司其职:js做状态管理
- 结构、API、控制流分离设计UI组件
- 插件和模版化,并抽象出组件模型
- 运用过程抽象的技巧来抽象并优化局部API