防抖
概念
用户操作触发事件频繁,只要最后一次的操作
使用场景
<body>
<input type="text">
<script>
let inp = document.querySelector("input")
inp.oninput = function() {
console.log(this.value);
}
</script>
</body>
当我们在输入框中输入一个“前”字时,以上代码在执行时,会出现如下图所示的情况
仅输入一个“前”字函数就执行了五次。那么当我们输入的字符串很长时,函数执行的次数也会变得很多;如果我们要发送请求的话,请求会变得非常频繁,导致性能下降;
如何把函数执行的次数降低,就是防抖的使用场景
第一种方式-非立即执行
当用户进行输入时,不会立即执行函数,而是等待 n 秒后再去执行函数,如果在此期间用户有新的输入,则重新计算 n;
let inp = document.querySelector("input")
let timer = null
inp.oninput = function () {
if (timer !== null) {
clearTimeout(timer)
}
timer = setTimeout(() => {
console.log(this.value);
}, 500)
}
第一种方式的优化
原理一样,只不过优化后的代码更容易维护,并且没有又创建一个全局变量
inp.oninput = debouce(function(){
console.log(this.value);
},500)
function debouce(fn, delayTime) {
let timer = null
return function () {
if (timer !== null) {
clearTimeout(timer)
}
timer = setTimeout(() => {
fn.call(this)
}, delayTime)
}
}
第二种方式-立即执行
用户第一次输入时立刻触发,然后n秒后不触发该事件才能继续执行函数
function debouce(fn, delayTime) {
let timer = null
let flag = true
return function () {
clearTimeout(timer)
if(flag) {
fn.call(this)
flag = false
}
timer = setTimeout(() => {
flag = true
}, delayTime)
}
}
结合版本
function debounce_merge(fn,delayTime = 500,isImmediate = false){
let timer= null;
let flag = true;
if(isImmediate){
return function(){
clearTimeout(timer);
if(flag){
fn.call(this);
flag = false
}
timer = setTimeout(() => { flag = true},delayTime)
}
}
return function(){
clearTimeout(timerId);
timer = setTimeout(() => {
fn.call(this)
},delayTime)
}
}
节流
概念
用户触发事件频繁,减少事件执行的次数;如触发1000次,使用节流使其触发次数减少到10
使用场景
<body>
<script>
window.onscroll = ()=> {
console.log("hello world!");
}
//
</script>
</body>
当我们滚动上图代码展示的页面时 会发生这样的效果
稍微滚动,函数就会被执行很多次;我们想让其执行次数减少到我们想让它执行的次数,这时候我们就要用到节流了
第一种方法 - 非立即执行
通过定时器限定多久执行一次
let flag = true
window.onscroll = ()=> {
if(flag) {
setTimeout(()=> {
console.log("Hello world");
flag = true
},500)
}
flag = false
}
函数优化
优化方法与防抖函数的优化相同
window.onscroll = throttle(function(){
console.log(this.value);
},500)
function throttle(fn, delayTime) {
let flag = true
return function () {
if (flag) {
setTimeout(() => {
fn()
flag = true
}, delayTime)
}
flag = false
}
}
第二种方法 - 立即执行
function throttle(fn, delayTime) {
let flag = true
return function () {
if (flag) {
setTimeout(() => {
fn()
flag = true
}, delayTime)
}
flag = false
}
}
第三种方法 - 时间戳版本
创建时间戳,在时间戳内,函数只执行一次
window.onscroll = throttle(function(){
console.log("Hello world!");
},1000)
function throttle(fn, delayTime) {
let pre = 0
return function(){
let now = Date.now()
if(now-pre>delayTime) {
fn.call(this)
pre = now
}
}
}
总结
- 相同点
- 防抖与节流都是为了防止函数在短时间内被频繁的触发
- 不同点
-
防抖函数只执行最后一次的操作,类似游戏中的回城,在回城期间,进行操作会打断回城
-
节流类似将多个操作合并为一个,类似于游戏中的技能释放,释放后技能会进入CD,CD完成后才能再次进行施法
-