之前在vue项目开发中遇到过模糊查询seach功能搜索抖动强烈,最后采用的是定时器解决的,现在贴上代码
watch: {
// 监听搜索框的数据 不为空时请求数据
searchInfo(val) {
this.showNoMore = false
if (this.timer) {
clearTimeout(this.timer)
}
this.timer = setTimeout(() => {
this.$showLoading()
if (!this.$isEmpty(val)) {
this.showNoMore = false
this.decodeNews = []
this.decodeStocks = []
this.decodeVideos = []
this.investmentCourse = []
// this.getehtId(this.getDecodeNewsData)
// this.getehtId(this.getDecodeVideo)
this.getehtId(this.getSearchInfo)
} else {
this.$hideLoading()
this.decodeNews = []
this.decodeStocks = []
this.decodeVideos = []
this.investmentCourse = []
}
}, 200)
}
}
在前端开发的过程中,我们经常会需要绑定一些持续触发的事件,如 resize、scroll、mousemove 等等,但有些时候我们并不希望在事件持续触发的过程中那么频繁地去执行函数。
通常这种情况下我们怎么去解决的呢?一般来讲,防抖和节流是比较好的解决方案。
让我们先来看看在事件持续触发的过程中频繁执行函数是怎样的一种情况。
<div id="content" style="height:150px;line-height:150px;text-align:center; color: #fff;background-color:#ccc;font-size:80px;"></div>
<script>
let num = 1;
let content = document.getElementById('content');
function count() {
content.innerHTML = num++;
};
content.onmousemove = count;
</script>
可以看到,在没有通过其它操作的情况下,函数被频繁地执行导致页面上数据变化特别快。所以,接下来让我们来看看防抖和节流是如何去解决这个问题的。
防抖
所谓防抖,就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。防抖函数分为非立即执行版和立即执行版。
非立即执行版 非立即执行版的意思是触发事件后函数不会立即执行,而是在 n 秒后执行,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。
<div id="content" style="height:150px;line-height:150px;text-align:center; color: #fff;background-color:#ccc;font-size:80px;"></div>
<script>
let num = 1;
let content = document.getElementById('content');
function count() {
content.innerHTML = num++;
};
function debounce(func, wait) {
let timeout;
return function () {
let context = this;
let args = arguments;
if (timeout) clearTimeout(timeout);
timeout = setTimeout(() => {
func.apply(context, args)
// count() 同等效果
}, wait);
}
}
content.onmousemove = debounce(count,1000);
</script>
防抖函数的代码使用这两行代码来获取 this 和 参数,是为了让 debounce 函数最终返回的函数 this 指向不变以及依旧能接受到 e 参数。
立即执行版 立即执行版的意思是触发事件后函数会立即执行,然后 n 秒内不触发事件才能继续执行函数的效果。
<div id="content" style="height:150px;line-height:150px;text-align:center; color: #fff;background-color:#ccc;font-size:80px;"></div>
<script>
let num = 1;
let content = document.getElementById('content');
function count() {
content.innerHTML = num++;
};
function debounce(func, wait) {
let timeout;
return function () {
let context = this;
let args = arguments;
if (timeout) clearTimeout(timeout);
let callNow = !timeout
timeout = setTimeout(() => {
timeout = null;
}, wait);
if(callNow) func.apply(context, args)
}
}
content.onmousemove = debounce(count,1000);
</script>
节流
所谓节流,就是指连续触发事件但是在 n 秒中只执行一次函数。节流会稀释函数的执行频率。
时间戳版:可以看到,在持续触发事件的过程中,函数会立即执行,并且每 1s 执行一次。
<div id="content" style="height:150px;line-height:150px;text-align:center; color: #fff;background-color:#ccc;font-size:80px;"></div>
<script>
let num = 1;
let content = document.getElementById('content');
function count() {
content.innerHTML = num++;
};
// func 函数 wait延迟执行毫秒数 immediate true表示立即执行 false表非立即执行
function throttle(func, wait) {
let previous = 0;
return function() {
let now = Date.now();
let context = this;
let args = arguments;
if(now - previous > wait) {
func.apply(context, args);
previous = now;
}
}
}
content.onmousemove = throttle(count,1000);
</script>
定时器版:在持续触发事件的过程中,函数不会立即执行,并且每 1s 执行一次,在停止触发事件后,函数还会再执行一次。
<div id="content" style="height:150px;line-height:150px;text-align:center; color: #fff;background-color:#ccc;font-size:80px;"></div>
<script>
let num = 1;
let content = document.getElementById('content');
function count() {
content.innerHTML = num++;
};
function throttle(func, wait) {
let timeout;
return function() {
let context = this;
let args = arguments;
if (!timeout) {
timeout = setTimeout(() => {
timeout = null;
func.apply(context, args)
}, wait)
}
}
}
content.onmousemove = throttle(count,1000);
</script>