快速理解防抖节流及运用场景

120 阅读2分钟

防抖节流(性能优化)

说明

防抖和节流各有特点,在不同的场景要根据需求合理的选择。如果事件触发是高频但是有停顿时,可以选择防抖; 在事件连续不断高频触发时,只能选择节流。因为debounce可能会导致动作只被执行一次,界面出现跳跃

image-20220609170242532.png

防抖

一直触发,触发动作结束(只执行一次):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不会立即执行,而是返回对应的函数,需要手动执行一下