Vue3 防抖和节流

966 阅读2分钟

  本文主要介绍了防抖节流的基本知识和使用过程。文章中不仅会讲述原来使用的防抖或节流方式,还会带来新的一种封装方式,使用起来更简单、更清晰。   在前端的开发过程中,在涉及到与用户交互的过程中是基本上都是需要处理的,常规操作就是在对应位置加上防抖或者节流。   加上防抖或者节流的作用:一是为了防止用户频繁操作;二是为了节约一定的服务器资源,减少资源浪费的情况。

节流(Throttle)

  节流是指在一段时间内,无论事件被触发多少次,都只执行一次处理函数。
  应用场景: 页面滚动,鼠标点击
  示例代码:

// 定时器闭包实现
function throttle(func, delay:1000) {
	let _time = null;
  	return function () {
    	let context = this;
    	let args = arguments;
     	if (_time) return
     	_timer = setTimeout(() => {
         clearTimeout(_timer)
         _timer = null
         // 改变函数内部的值
         func.apply(context, args);
      	}, delay)
	}
}

// 时间戳闭包实现
function throttle(func, delay:1000) {
	let lastTime = 0;
    return function () {
    	let context = this;
    	let args = arguments;
    	let now = Date.now();
    	if (now - lastTime >= delay) {
    		// 更新时间
      		lastTime = now;
      		func.apply(context, args);
    	}
  	}
}

// 使用
let count = 0
throttle(() => count += 1, 1000)

防抖(debounce)

  防抖是指当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前,又一次触发了事件,就重新开始延时。
  应用场景: 搜索框、窗口大小调整
  示例代码:

// 定时器不闭包实现
function debounce(func, delay:1000) {
	let timer = null;
    clearTimeout(timer);
    timer = setTimeout(() => {
      func;
    }, delay);
}

// 定时器闭包实现
function debounce(func, delay:1000) {
  let timer = null;
  return function () {
    let context = this;
    let args = arguments;
    clearTimeout(timer);
    timer = setTimeout(function () {
      func.apply(context, args);
    }, delay);
  }
}

// 使用
let count = 0
debounce(() => count += 1, 1000)

提升(响应式的防抖和节流)

  在Vue3中,可以使用customRef来实现响应式的防抖与节流   customRef 可以用来创建一个自定义的ref,并对其依赖项跟踪和更新触发进行显式控制
  执行过程: 当数据value发生了变化,就会触发set函数,set接收变化后的数据newValue,newValue在定时函数中被赋予给value,然后通过get,将变化后的value给return出去
  示例代码:

// 节流
export default function useThrottle(data, delay = 300) {
    // 创建定时器
    let timer = null;
    return customRef((track, trigger) => {
    	return {
    		get() {
    			track() // 收集依赖
    			return value
    		},
    		set(newValue) {
    			// 清除定时器
                if(timer != null){
                	clearTimeout(timer)
                    timer = null
                }
                // 创建定时器
                timer = setTimeout(() => {
                    // 修改数据
                    data = value;
                    // 派发更新
                    trigger()
                }, delay)
    		}
    	}
    })
}

// 防抖
export default function useDebounce(value, delay = 200) {
  	let timeout = null
  	return customRef((track, trigger) => {
    	return {
	    	get() {
	        	track() // 收集依赖
	        	return value
	      	},
      		// newValue 值
	      	set(newValue) {
	      		// 清除定时器
	        	if(timer != null){
	        		clearTimeout(timer)
	            	timer = null
	        	}
	        	clearTimeout(timeout)
	        	timeout = setTimeout(() => {
	          	value = newValue
	          	trigger() // 派发更新
	        	}, delay)
	      	}
      	}
   })
}

  使用:

<template>
	<input type='text' v-model='keyword' />
</template>

<script setup>
	import { useThrottle, useDebounce } from './'
	const keyword = useDebounce(0, 1000)
</script>