1、什么是节流和防抖
用来解决一种问题: 代码可能会短时间内频繁调用,那么会造成性能浪费
先明确一个定义节流跟防抖有不同的应用场景,不要混为一谈
2、防抖解读
如果短时间内频繁触发,就不执行代码,等过了一段时间才执行代码
关键点是利用定时器,如果你频繁操作,它就频繁结束旧定时器,开启新的定时器,就保证了只有等你操作完了才执行代码、频繁操作只有最后一次才执行
3、防抖的思想
如果频繁的操作,可能会不断的频繁执行代码,要想办法,让代码在我们操作停一会时才触发
实现步骤:把要执行的代码放到定时器里,如果频繁的触发,我们就频繁的刷新定时器
直到没有频繁触发了,定时器里的代码才开始执行
4、代码操作
let timerId = null
//滚动条监听函数
window.onscroll = function () {clearTimeout(timerId)// 频繁操作时,我不断的停掉的定时器// 再开启新的定时器,那么里面代码不会被执行// 只有等我停500毫秒才会执行timerId = setTimeout(() => {console.log('发请求的代码')}, 200);
}
不断刷新定时器只有最后一次操作才执行
5、防抖的应用场景
网站内容搜索,他不是说你输入一个字就发一个请求搜一下而是在你输入完内容的多少秒之后才进行ajax请求发送。中间如果有继续的文字输入就刷新定时器从新计算时间。
6、节流解读
是指代码在频繁操作下还是会执行,但是上次没执行,不会执行下一次,只有等上一次执行完了,才会开启下一次的执行,利用开关思想,准备一个用来标记的变量 (拉屎开关门一个道理)
只有当上一个操作执行完了才执行下一个
7、代码操作
// 这个开关相当于是判断任务执行完了没有
let flag = true
//滚动条监听函数
window.onscroll = function () {// 如果为true,代表执行完了,可以开始再次执行if (flag) {// 马上把这个标记改成false,代表还没有执行完flag = false// 我们就用setTimeout模拟是发请求的代码setTimeout(() => {console.log('请求完了')flag = true}, 1500);}
}
8、节流的应用场景
验证码倒计时,轮播图按钮限流
一般我们应用在倒计时发送验证码当用户点击按钮进行倒计时,不小心再次点击,这样倒计时会重新进行计数,这样对用户体验很不好,或者在轮播图左右按钮切换过快的问题
9、Lodash库的节流防抖
9.1、Lodash是什么?
Lodash 是一个一致性、模块化、高性能的 JavaScript 实用工具库。
Lodash 通过降低 array
、number
、objects
、string
等等的使用难度从而让 JavaScript 变得更简单。
Lodash 的模块化方法 非常适用于: 遍历 array、object和String,对值进行操作和检测,创建符合功能的函数
9.2、安装Lodash
npm i --save lodash
9.3、使用防抖
防抖简述:在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。
应用场景:搜索框防抖,如果用户只要输入一个字符就会触发请求,不仅从资源上来说是很浪费的,而且实际应用中,用户也是输出完整的字符后,才请求
<div class=''><input type="text" v-model="value" @input="input" />
</div>
<script>
// 引入lodash
import _ from 'lodash'
export default {data() {return {value:''};},methods: {input:_.debounce(()=>{console.log(this); // undefined},1000)}
};
</script>
在vue中methods箭头函数的this指向undefined问题:以上代码在浏览器会输出undefined
。哎,不应该指向window
吗?
搞清楚这个问题,我们首先要知道:
- 箭头函数的this指向父级作用域的this
vue
默认开启了严格模式- 全局作用域下的函数this指向window,在严格模式下指向undefined
所以在debounce里面不要使用箭头函数,所以我们得改改
methods: {input:_.debounce(function(){console.log(this.value);},1000)
}
9.4、使用节流
节流简述:在一个单位时间内,只能触发一次
应用场景:验证码倒计时,轮播图按钮限流
应用场景简述:一般我们应用在倒计时发送验证码当用户点击按钮进行倒计时,不小心再次点击,这样倒计时会重新进行计数,这样对用户体验很不好,或者在轮播图左右按钮切换过快的问题
methods: {input:_.throttle(function(){console.log(this.value);},1000)
}