引言
在现代Web开发中,全栈开发者不仅需要掌握前端技术,还需熟悉后端服务的设计与实现。为了提高应用的性能和用户体验,前后端分离和防抖技术成为了不可或缺的工具。本文将介绍如何通过前后端分离解耦、使用live-server和json-server进行开发,以及探讨Array.prototype上的filter、map方法,并重点讲解防抖技术的实现与应用。
前后端分离与解耦
前后端分离是一种开发架构,它将前端用户界面(UI)与后端逻辑服务分离,通过API接口进行数据交互。这种架构不仅提高了开发效率,还使得前后端可以独立部署和升级,增强了系统的可扩展性和可维护性。
- 前端:使用
live-server在5500端口运行,负责展示用户界面和交互逻辑。前端通过fetch请求访问后端提供的RESTful API接口服务,获取数据并展示。 - 后端:使用
json-server在3001端口运行,模拟RESTful API接口,提供数据服务。json-server是一个轻量级、零配置的JSON API服务器,非常适合用于前端开发的模拟环境。
项目介绍
实现一个用户搜索功能。
项目初始化和开发环境启动
撸代码前呢先做好以下步骤:(我先创建了一个throttle_debounce文件夹然后在该文件夹下面分别创建backend和frontend文件夹,然后再使用 cd 命令导航到backend的根目录下面执行以下命令)
npm init -y //初始化为后端项目,得到 package.json 如图所示的3
npm i json-server // `npm` 会从 npm 仓库中下载 `json-server` 包及其所需的依赖项,并将它们存储在项目的 `node_modules` 目录中,如图所示的4
npm i // `npm` 会根据 `package.json` 中列出的所有依赖项进行安装。
对于每个依赖项,`npm` 会将其确切的版本号、下载地址、完整性校验信息等存储在 `package-lock.json` 中(如图所示2)。
接下来在backend文件夹下创建一个json数据文件(db.json文件上图所示的1)添加数据,如下图左图所示。 接着在package.json文件里面如下图右图画圈部分添加一个脚本:"dev": "json-server --watch db.json --port 3001"
"dev"是脚本的名称,它是一个自定义的名称,通常用于开发环境相关的操作。
"json-server --watch db.json --port 3001"是该脚本的具体命令:
json-server是一个工具,它可以根据一个 JSON 文件快速创建一个简单的 RESTful 服务器。
--watch db.json指示json-server工具要监视db.json文件。这意味着当db.json文件的内容发生变化时,服务器会自动更新其提供的数据,以反映这些变化。
--port 3001是一个参数,指定了json-server运行的端口号为 3001。 接着在终端运行:npm run dev //用于运行package.json中scripts部分定义的脚本。
最后frontend文件夹下面创建index.html和index2.html用于编写前端代码
代码部分
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</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() {
let value = this.value.trim();
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("")
// for(let user of filterUsers) {
// const oLI = document.createElement('li');
// oLI.innerText = user.name;
// oUL.appendChild(oLI);
// }
})
})
</script>
</body>
</html>
效果展示
搜索功能实现了,但是存在一个致命的缺点——没有实现防抖功能: 在编程和软件开发中,特别是在处理用户输入、窗口调整大小、滚动事件或任何频繁触发的事件时,如果不使用防抖(debounce)技术,可能会导致性能问题或用户体验不佳。如果在公司工作不实现防抖技术,影响代码性能,消耗大量CPU资源甚至造成项目崩溃,那就只能提桶跑路了
防抖
防抖(Debounce)是一种编程技术,用于限制某个函数在特定时间间隔内的执行次数。当事件被频繁触发时(例如,用户快速连续点击按钮),防抖技术可以确保目标函数不会立即执行,而是在最后一次事件触发后的指定延迟时间结束时执行一次以下是修改代码。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</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 指向事件的目标元素
const debounceNameSearch = debounce(handleNameSearch, 500);
oInput.addEventListener('keyup', debounceNameSearch)
function handleNameSearch() {
let value = oInput.value.trim();
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("")
// for(let user of filterUsers) {
// const oLI = document.createElement('li');
// oLI.innerText = user.name;
// oUL.appendChild(oLI);
// }
})
}
// 防抖
// 高阶函数
function debounce(fn, delay) {
let id;
return function() {
// 限流
clearTimeout(id);
id=setTimeout(()=>{
fn();
},delay)
}
}
</script>
</body>
</html>
以下是对代码中防抖实现的解释:
防抖函数
debounce:
javascript
function debounce(fn, delay) { let id; return function() { // 清除之前设置的定时器 clearTimeout(id); // 设置新的定时器 id = setTimeout(() => { fn(); }, delay); } }
let id;:声明一个变量id,用于存储setTimeout的标识符。return function() {...}:返回一个新的函数,这个函数将作为事件处理函数。clearTimeout(id);:每次调用这个新函数时,会清除之前设置的setTimeout定时器。这样做的目的是,如果在延迟时间delay内多次调用该函数,之前的定时器会被取消,不会执行fn函数。id = setTimeout(() => { fn(); }, delay);:设置一个新的setTimeout定时器,在延迟delay毫秒后调用fn函数。使用防抖函数:
javascript
const debounceNameSearch = debounce(handleNameSearch, 500); oInput.addEventListener('keyup', debounceNameSearch);
const debounceNameSearch = debounce(handleNameSearch, 500);:将handleNameSearch函数和延迟时间 500 毫秒传递给debounce函数,得到一个经过防抖处理的新函数debounceNameSearch。oInput.addEventListener('keyup', debounceNameSearch);:为输入框添加keyup事件监听器,当用户在输入框中输入内容并松开键盘按键时,会触发keyup事件,调用debounceNameSearch函数。工作原理:
- 当用户在输入框中输入内容时,每次按键抬起(
keyup事件)都会调用debounceNameSearch函数。- 由于
debounceNameSearch是经过debounce函数处理的,它会清除之前的定时器(如果存在),并设置一个新的定时器。- 只有当用户停止输入超过 500 毫秒(延迟时间)时,
handleNameSearch函数才会被调用,从而避免了频繁调用handleNameSearch函数,实现了防抖效果。例如,假设用户连续输入 "abc",会触发三次
keyup事件:
- 输入 "a" 时,设置一个 500 毫秒的定时器。
- 输入 "b" 时,清除之前的定时器,重新设置一个 500 毫秒的定时器。
- 输入 "c" 时,再次清除之前的定时器,重新设置一个 500 毫秒的定时器。
这样,只有在用户停止输入 500 毫秒后,
handleNameSearch函数才会被调用,避免了在用户快速输入时频繁调用handleNameSearch函数,减少了不必要的请求和性能开销。总之,通过
debounce函数和setTimeout机制,实现了对handleNameSearch函数的防抖处理,提高了性能和用户体验。
效果展示
结语
通过前后端分离和防抖技术的结合,全栈开发者可以构建高性能、用户体验良好的Web应用。前后端分离提高了开发效率和系统的可扩展性,而防抖技术则有效减少了不必要的函数执行,提升了应用的响应速度和性能。掌握这些技术和方法,将帮助开发者更好地应对现代Web开发的挑战