引言
作为一个前端开发者,防抖技术是一个必备技能,,也是面试中经常被问到的面试题,但是很多没有实战经验的前端开发者对这个功能有点摸不着头脑。那么让我们一起通过手搓一个小项目来搞懂防抖功能吧!
项目实战
如果你是一个新手,首先让我们来了解一下现在的开发模式
前后端分离是现代 Web 开发中的一种架构模式指的是将前端(用户界面和交互逻辑)与后端(业务逻辑和数据处理)代码分离开来,彼此独立开发、测试和部署。前后端通过接口(API)进行通信,通常使用 HTTP 协议和 JSON 数据格式。
简单来说就是前端负责页面设计而后端负责数据资源,前后端再通过接口连接
话不多说,让我们开始吧!
第一步 创建一个throttle文件夹,再在这个文件夹里面创建frontend(前端)和backend(后端)文件夹再在backend目录下执行以下命令
npm init -y //初始化为一个后端项目,得到package.json
npm i json-server //安装 `json-server` 包的命令,帮助你快速搭建一个 RESTful API 服务器
npm i //用于安装项目依赖,npm 会读取 `package.json` 文件中的依赖项列表,并自动下载和安装所有列出的包及其依赖。
再继续再backend文件夹下创建一个json文件夹,添加数据
我创建的为db.json,然后你往里面写入一些数据
{
"users": [
{
"id": "1",
"name": "小汪"
},
{
"id": "2",
"name": "小米"
},
{
"id": "3",
"name": "尼达"
}
],
"posts": [
{
"id": "1",
"title": "学习APIfox",
"body": "React is a JavaScript library for building user interfaces.",
"published": true,
"authorId": 1
},
{
"id": 2,
"title": "REACT+JSON-SERver 全栈快跑",
"body": "React is a JavaScript library for building user interfaces.",
"published": true,
"authorId": 2
}
]
}
再打开package.json文件夹找到scripts
代码解读
scripts": {...}
:这是一个 JSON 对象中的属性,用于定义项目的脚本命令。
-
"dev": "json-server --watch db.json --port 3001"
:-
"dev"
是脚本的名称,它可以自拟定,通常用于开发环境。 -
"json-server --watch db.json --port 3001"
是该脚本的具体命令。json-server
:是一个用于快速搭建 RESTful JSON 服务器的工具。--watch db.json
:表示让json-server
监视db.json
文件的变化,当db.json
文件内容发生改变时,服务器会自动更新相应的数据。--port 3001
:指定服务器运行的端口为 3001。
-
到这里后端部分的工作就做完了
前端部分
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>防抖</title>
</head>
<body>
<div>
<label for="unDebounceInput">用户搜索</label>
<input
type="text"
id="unDebounceInput"
placeholder="请输入要搜索的用户名字"
>
</div>
<ul id="users">
</ul>
<script>
const oUL = document.querySelector('#users');
// 通往后端接口
const oInput = document.getElementById('unDebounceInput');
// 当作为事件的处理函数来用时,this 指向事件的目标元素
oInput.addEventListener('keyup', function() {
// 获取 oInput 的值并去除前后空格
let value = this.value.trim();
// 检查value是否为空,若为空则清除oul的内容
if (value === '') {
oUL.innerHTML = '';
return;
}
// 调用接口,这就是前端和后端连接的关键
fetch('http://localhost:3001/users')
.then(res => res.json())
.then(users => {
// console.log(users);
// 箭头函数的优雅 + filter 的新功能
const filterUsers = users.filter(
user => user.name.includes(value)
)
// Array 在es6 中新增的方法
oUL.innerHTML = filterUsers.map(user => `
<li>
${user.name}
</li>
`
).join("")
})
})
</script>
</body>
</html>
这样就完成了一个简单的用户查找页面,前端通过调用后端提供的 API 接口与后端进行通信。这个请求的具体含义是:前端应用程序尝试从运行在 localhost
(本地计算机)上的服务器、并且监听在 3001 端口的服务获取 /users
路径下的资源
但这里其实是有一个很重要的问题,要是你没有处理就直接提交上线了,那么可能你就得删除数据库跑路了
请看
这有什么问题呢?
用户在输入框一输入就立马向服务器发送几次请求,可能用户刚输入一个字就已经请求上百次了,如果是是像百度这样的同一时间可能有成百万的用户进行搜索,就是再大的服务器都得奔溃啊!
那要怎么解决这个问题呢?
哎,这就来到了我们今天的主题了:防抖
防抖(Debounce)
防抖是一种优化技术,用于限制高频触发的事件,使事件在一段时间内只执行一次。它通常应用在以下场景:
- 用户输入时避免频繁请求(如搜索框联想)
- 滚动事件(如懒加载)
- 窗口大小变化事件的回调函数
基本原理
- 延迟执行
每次触发事件时,都会启动一个计时器。如果在计时器时间内事件再次触发,则重置计时器。 - 只执行最后一次
当一段时间内没有新事件触发时,计时器才会执行回调函数。
实现
function debounce(fn,delay){
let id;
return function(){
clearTimeout(id);// 清除定时器 防止多次触发 只执行最后一次
id=setTimeout(()=>{
fn()
},delay)
}
}
代码解释:
-
debounce
函数是一个防抖函数,它接收两个参数:fn
(要执行的函数)和delay
(延迟时间)。-
首先,它声明了一个变量
id
,用于存储定时器的标识符。 -
然后,它返回一个匿名函数。
- 当这个匿名函数被调用时,它会先使用
clearTimeout(id)
清除之前设置的定时器,防止多次触发。 - 接着,它会使用
setTimeout
函数创建一个新的定时器,在delay
毫秒后调用fn
函数。 - 新创建的定时器的标识符存储在
id
变量中,以便下次调用匿名函数时可以清除它
- 当这个匿名函数被调用时,它会先使用
-
所以我们只需要用这个函数来监听输入框输入事件,当用户在输入框中输入时,debounceNameSearch
会被触发,但 handleNameSearch
函数只会在用户停止输入 500 毫秒后才会执行,而不是每次输入一个字符就执行一次,提高了性能和用户体验,也防止了服务器访问量过大导致服务器奔溃了
总结
- 防抖适合处理短时间高频事件,以减少无效调用。
防抖是一种有效的手段,可以帮助减少不必要的计算和网络请求,提高应用性能。通过合理地应用防抖,你可以显著改善应用程序的响应性和效率。