防抖
一、什么是防抖?
防抖阻止了事件的多次调用,规定时间内只会执行一次。
二、防抖解决了什么问题
假设一个用户高频点击一个按钮,点击按钮后会向后台发送请求,如果不使用防抖,就会发送许多重复的Ajax请求,造成服务器压力。使用防抖后,规定时间内,只会发送一次Ajax请求,可以有效地减缓服务器的压力。
三、实现防抖的基本代码
通过监听输入框的输入事件,通过定时器每隔一秒获取一次用户输入的内容,如果一秒内用户又进行了输入,清除上一次的定时器,重新计时一秒,计时结束后将用户输入的内容打印到控制台。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>debounce</title>
</head>
<body>
<input type="text" placeholder="请输入您要搜索的内容~" />
<script>
let timer = null
$('input').on('input',function(){
console.log('没有防抖',$('input').val())
// 向清除一次定时器
clearTimeout(timer)
// 重新开启一个定时器
timer = setTimeout(() => {
// 如果input输入框的值为空,就终止执行后面的代码
if(!$('input').val()) return
console.log('加了防抖后',$(this).val())
}, 1000);
})
// $('input').on(
// 'input',
// debounce(function () {
// if (!$(this).val()) return
// console.log($(this).val())
// })
// )
// // 封装代码,提高代码的复用性
// function debounce(fn) {
// let timer = null
// return function () {
// clearTimeout(timer)
// timer = setTimeout(() => {
// // 这里的 this 指向 window
// // 通过 call() 方法改变this的指向
// fn.call(this)
// }, 1000)
// }
// }
</script>
</body>
</html>
四、防抖的应用场景
想必大家平时都有逛购物网站的习惯,当我们在搜索框搜索某件商品时,只要输入关键字就会在搜索框下出现对应的联想列表。但是联想列表不是实时展示的,可以延迟500毫秒或者1秒,将用户输入的关键字通过Ajax请求提交给后台,当得到后台服务器响应后,再将联想列表展示给用户。这样的操作大大地减少了对服务器的请求压力,延迟适当的时间,也可以让用户有足够的时间将想要搜索的关键字写完整。
1.代码实现
代码如下(示例):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>防抖</title>
<style>
* {
margin: 0;
padding: 0;
}
div {
width: 500px;
margin: auto;
}
.box {
margin-top: 200px;
width: 500px;
height: 35px;
border: 1px solid #ccc;
border-radius: 8px;
overflow: hidden;
}
a {
text-decoration: none;
color: #fff;
width: 60px;
height: 100%;
line-height: 35px;
text-align: center;
background-color: steelblue;
}
.fl {
float: left;
}
.fr {
float: right;
}
input {
padding-left: 20px;
width: 418px;
height: 100%;
border: 0;
outline: none;
}
.list {
display: none;
width: 500px;
border: 1px solid #ccc;
border-top: none;
border-radius: 8px;
}
li {
list-style: none;
padding-left: 30px;
height: 30px;
line-height: 30px;
border-bottom: 1px solid #ccc;
}
li:last-child {
border-bottom: none;
}
</style>
</head>
<body>
<div class="box">
<input type="text" class="fl" placeholder="请输入您要搜索的内容~" />
<a href="javascript:;" class="fr">搜索</a>
</div>
<div class="list">
<ul></ul>
</div>
<script src="./jquery-3.5.1.min.js"></script>
<script>
let timer = null
// 给input输入框绑定input事件
$('input').on('input', function () {
clearTimeout(timer)
timer = setTimeout(() => {
// 如果输入框的内容为空,就终止代码的执行
if (!$(this).val()) return
let kw = $(this).val()
// 发送Ajax请求
$.ajax({
type: 'GET',
url: 'http://www.liulongbin.top:8000/v1_0/suggestion?q=' + kw,
success: function (res) {
// 判断服务器返回的结果,如果没有内容弹框提示并终止后续代码执行
if (res.data.options.length === 0) {
alert('暂时没有搜索结果~')
$('input').val('')
return
}
// 遍历服务器返回的数据
res.data.options.forEach(item => {
// 将每一项追加到ul列表中
$('.list ul').append(`<li>${item}</li>`)
})
// 展示联想列表
$('.list').show()
}
})
}, 1000)
// 隐藏联想列表展示并清空ul内的内容
$('.list').hide().find('ul').empty()
})
</script>
</body>
</html>
节流
一、应用场景
用户选择手机号和验证码登录的时候,往往需要填写手机号后,点击发送验证码来进行后续操作。那么发送验证码的动作应该有一个限制,不然用户一直点击按钮,不但会给用户带来经济损失,也会发送很不必要的请求给后台。
所以对用户点击发送验证码后的按钮,进行一个倒计时的防抖操作是必须的。
二、代码演示
用到的button全局组件 ===》vue3——自己封装按钮组件
使用@vueuse/core中的useIntervalFn来帮助我们完成这项工作
首先需要在项目根目录下打开任意终端,执行npm i @vueuse/core@5.3.0
代码如下(示例):
<template>
<div class="home-container">
<my-button type="plain" size="middle" @click="sendCode">{{
timer === 0 ? '发送验证码' : `${timer}s后重新获取`
}}</my-button>
</div>
</template>
<script>
import { ref } from 'vue'
import { useIntervalFn } from '@vueuse/core'
export default {
name: 'App',
setup() {
// 倒计时
const timer = ref(0)
// 发送验证码倒计时
// useIntervalFn(定时的回调,回调的时间间隔,控制回调的调用方式)
// 参数三 {immediate: true, immediateCallback: false}
// 3-1) immediate 首次运行useIntervalFn函数时,是否立刻开启定时任务(默认值true表示默认开启)
// 3-2)immediateCallback 执行useIntervalFn函数立刻执行回调(在延时时间的前或者后调用),默认值是false,如果修改为true,表示为不延时,立刻启动定时任务(不要使用pause方法)
// pause暂停;resume启动
const { pause, resume } = useIntervalFn(
() => {
if (timer.value <= 0) {
// 停止定时任务
pause()
} else {
// 单次定时任务执行的回调
timer.value--
}
},
1000,
{
// 默认不开启定时任务
immediate: false
}
)
// 发送验证码
const sendCode = () => {
// 开启倒计时效果
if (timer.value === 0) {
timer.value = 60
resume()
} else {
return
}
// 这里写向后台发送请求的代码
console.log('发送请求')
}
return { timer, sendCode }
}
}
</script>
<style lang="less">
.home-container {
margin: 100px auto;
width: 300px;
height: 100px;
}
</style>