组件设计的原则:封装性,正确性,扩展性,复用性
实现组件的步骤:结构设计 展现效果 行为设计
三次重构:
插件化
模板化
抽象化
使用高阶函数来防止多次触发事件 Once
为了能够让“只执行一次”的需求覆盖不同的事件处理,我们可以将这个需求剥离出来 称为过程抽象
function once(fn){
return function(...args){
if(fn){
const ret = fn.apply(this , args)
fn =null
return ret
}
}
}
我们可以理解为函数**参数fn 与 return function(...args)**等价
HOF(高阶函数)
以函数为参数 以函数为返回值 常用于作为函数装饰器
节流防抖
运用场景: 限制函数的执行频次,从而优化函数触发频率过高导致的响应速度跟不上触发频率,导致出现延迟、卡顿的现象以及其他错误
通常用于一些高频率的事件中,比如 鼠标滚动、窗口resize、滚动条滑动 等操作。在这种情况下,我们希望这些事件能够以一定的频率触发(要触发多次),但不是每次事件都触发,节流函数可以规定在一定时间间隔中,该方法只执行一次。这样可以减少函数的执行次数,优化性能。举个简单例子,当用户拖动滚动条时,如果每次滚动都触发事件,页面就会非常频繁的更新UI,造成卡顿。使用节流函数可以限制触发频率,提升页面流畅度。
防抖:处理一些高频触发的事件,比如用户连续点击按钮、输入框频繁输入。 当用户点击按钮过快,导致重复点击,多次调用接口;或者输入框的文字一变化就调用接口,导致多次调用接口。
此时,我们肯定是希望哪怕多次点击按钮,也只调用一次接口;也不希望输入框每输入一个字母就发送一次请求,那样页面就会频繁地发送请求,极大的浪费资源。使用防抖可以在用户输入完毕后再发送请求,或者避免重复点击按钮重复请求,减少函数的执行次数及接口调用,避免频繁更新UI或者发送请求造成性能浪费。 简而言之就是不管触发了多少次回调都只执行最后一次
节流:对于连续触发的事件,每隔一段时间内执行一次,节流里面涉及的时间主要指时间执行的间隔时间。
简而言之就是无论触发多少次回调都只执行第一次
节流函数:
function throttle(fn , time = 500){
let timer;
return function(...args){
if(timer === null){
fn.apply(this,args)
timer = setTimeout(() =>{
timer = null;
),time)
}
}
}
}
//只有当timer === null条件成功才会触发函数
//只有经过time s后才能给timer = null条件
防抖函数:
function debounce(fn , dur){
dur = dur || 100
var timer
return function(){
clearTimout(timer)
timer = setTimeout(() => {
fn.apply(this,args)
},dur)
}
}
//只有当dur s之后才会触发定时器内的函数
//每一次调用都会把前一次的定时器给删除
声明式写法实现button三态
用shift拿到actions的第一个 然后将他push到最后 这样下一次执行就是之前的下一个
交通灯轮询效果
利用wait函数中返回的promise成功后使用的定时器来实现轮询
const traffic = document.getElementById('traffic');
function wait(time){
return new Promise(resolve => setTimeout(resolve, time));
}
function setState(state){
traffic.className = state;
}
async function start(){
//noprotect
while(1){
setState('wait');
await wait(1000);
setState('stop');
await wait(3000);
setState('pass');
await wait(3000);
}
}
start();
经典洗牌算法
const cards = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
function shuffle(cards) {
const c = [...cards];
for(let i = c.length; i > 0; i--) {
const pIdx = Math.floor(Math.random() * i);
[c[pIdx], c[i - 1]] = [c[i - 1], c[pIdx]];
}
return c;
}
分红包算法
切西瓜:将随机切一刀 挑被切的多的那一份再切
function generate(amount, count){
let ret = [amount];
while(count > 1){
//挑选出最大一块进行切分
let cake = Math.max(...ret),
idx = ret.indexOf(cake),
part = 1 + Math.floor((cake / 2) * Math.random()),
rest = cake - part;
ret.splice(idx, 1, part, rest);
count--;
}
return ret;
}