防抖节流(性能优化)
说明
防抖和节流各有特点,在不同的场景要根据需求合理的选择。如果事件触发是高频但是有停顿时,可以选择防抖; 在事件连续不断高频触发时,只能选择节流。因为debounce可能会导致动作只被执行一次,界面出现跳跃
防抖
一直触发,触发动作结束(只执行一次):input.change、window.resize
结构
<!--call,bind参数是列表形式,apply参数是数组形式 -->
<input v-model="test" @input="goInput(['圆圆', '滚滚'])"></input>
<input v-model="test" @input="goInput('圆圆', '滚滚')"></input>
js:在data中定义一个test变量
/**
* @desc 函数防抖
* @param fn 函数
* @param wait 延迟执行毫秒数
*/
const debounce = (fn, wait = 400) => {
let timeout;
return function () {
timeout && clearTimeout(timeout);
timeout = setTimeout(() => {
// fn.apply(this, ...arguments);
// fn.bind(this, ...arguments)();
fn.call(this,...arguments)
}, wait);
};
};
methods:{
goInput: debounce((a, b) => {console.log(a + b + '防抖')})// 圆圆滚滚防抖
}
节流
一直触发,触发期间,定时间隔执行一次: 鼠标滚动、下拉加载(在防抖的基础上,多了一个时间差)
结构
<!--call,bind参数是列表形式,apply参数是数组形式 -->
<input type="text" v-model="test" @input="goInput('圆圆', '滚滚')" />
<input type="text" v-model="test" @input="goInput(['圆圆', '滚滚'])" />
js:data中定义一个test变量
/**
* @desc 函数节流
* @param fn 函数
* @param wait 延迟执行毫秒数
* @param type 1 表时间戳版,2 表定时器版
*/
const throttle = (fn, wait = 400, type) => {
if (type === 1) {
var previous = 0;
} else if (type === 2) {
var timeout;
}
return function() {
let args = arguments;
if (type === 1) {
let now = Date.now();
if (now - previous > wait) {
// fn.apply(this, ...args);
// fn.bind(this, ...args)();
fn.call(this, ...args);
previous = now;
}
} else if (type === 2) {
if (!timeout) {
timeout = setTimeout(() => {
timeout = null;
// fn.apply(this, ...args);
// fn.bind(this, ...args)();
fn.call(this, ...args);
}, wait);
}
}
};
};
methods:{
goInput: throttle((a, b) => {console.log(a + b + "节流")},2000,1)// 圆圆滚滚节流
}
bind,call,apply的作用都是用来改变this指向的,可以传两个参数
参数一:this要指向的对象,如果如果没有这个参数或参数为undefined或null,则默认指向全局window
参数二:apply(数组形式),call(列表形式),bind(列表形式)
apply,call,会立即执行,bind不会立即执行,而是返回对应的函数,需要手动执行一下