前端工程师们都听过看起来很高级的词,节流和防抖,其实节流就是throttle,防抖就是debounce,其实这个也属于前端性能优化的一部分。前端
在作远程搜索时,若是每输入1个字就调用1次接口,就会频繁查询数据库,假设咱们的查询是"12345",不考虑用户输入错误的状况,至少会请求5次。vue
再思考一个问题,按钮的click重复触发(例如快速点击2次,3次,...n次)该如何在前端作一层拦截,避免发送重复请求到服务端,最多见的是新增时插入重复数据,这个问题该怎么办呢?git
<template> <input @input="handleInput"/> </template> <script> export default { name: 'input', data() { return { delay: 1000, count: 0, }; }, methods: { handleInput(e) { console.log(`debounce wait时间为${this.delay}ms`); console.log('触发了input事件', e.target.value); this.count++; console.log(`触发了${this.count}次远程搜索`); }, }, }; </script>
打印结果:
debounce wait时间为1000ms
触发了input事件 1
触发了1次远程搜索
debounce wait时间为1000ms
触发了input事件 12
触发了2次远程搜索
debounce wait时间为1000ms
触发了input事件 123
触发了3次远程搜索
debounce wait时间为1000ms
触发了input事件 1234
触发了4次远程搜索
debounce wait时间为1000ms
触发了input事件 12345
触发了5次远程搜索github
说明:输入5个数查询5次,形成了频繁查询数据库的行为,是一种性能浪费。数据库
有,能够为函数设置一个setTimeout函数,至关于定时调用接口,这种方法是低效的,也是很是愚蠢的,须要控制开关定时器,一旦搜索功能多了,就更蠢了。canvas
有,debounce(防抖)就是作这个事情的,lodash从0.1.0就支持了这个方法。segmentfault
<template> <input @input="debounceHandleInput"/> </template> <script> import _ from 'lodash'; export default { name: 'input-debounce', data() { return { delay: 1000, }; }, computed: { debounceHandleInput() { return _.debounce(this.handleInput, this.delay); }, }, methods: { handleInput(e) { console.log(`debounce wait时间为${this.delay}ms`); console.log('触发了input事件', e.target.value); this.count++; console.log(`触发了${this.count}次远程搜索`); }, }, }; </script>
打印结果:
debounce wait时间为1000ms
触发了input事件 12345后端
说明:在1000ms时间范围内触发,仅仅触发了一次远程搜索,也就是仅仅调用一次后端接口,达到咱们的预期效果。性能优化
<template> <input @input="throttleHandleInput"/> </template> <script> import _ from 'lodash'; export default { name: 'input-throttle', data() { return { delay: 1000, count: 0, }; }, computed: { throttleHandleInput() { return _.throttle(this.handleInput, this.delay); }, }, methods: { handleInput(e) { console.log(`throttle wait时间为${this.delay}ms`); console.log('触发了input事件', e.target.value); this.count++; console.log(`触发了${this.count}次远程搜索`); }, }, }; </script>
打印结果:
throttle wait时间为1000ms
触发了input事件 1
触发了1次远程搜索
throttle wait时间为1000ms
触发了input事件 12345微信
说明:在1000ms时间范围内触发,仅仅触发了2次远程搜索,调用2次后端接口。用户首次输入1当即返回数据,保证数据到达速度,也提高了用户体验。中间的12,123,1234被节流函数成功拦截避免触发。而12345是咱们最终须要的搜索结果,在最后返回给用户。达到咱们的预期效果。
<template> <button @click="handleClick">新增</button> </template> <script> export default { name: 'click', data() { return { count: 0, }; }, methods: { handleClick(e) { console.log('触发了click事件', e.target.value); this.count++; console.log(`触发了${this.count}次新增数据`); }, }, }; </script>
触发了click事件
触发了1次新增数据
触发了click事件
触发了2次新增数据
说明:快速点击2次“新增”按钮,而最终只触发了2次数据新增,形成重复数据插入。
<template> <button @click="debounceHandleClick">新增</button> </template> <script> import _ from 'lodash'; export default { name: 'click-debounce', data() { return { delay: 1000, count: 0, }; }, computed: { debounceHandleClick() { return _.debounce(this.handleClick, this.delay); }, }, methods: { handleClick(e) { console.log(`debounce wait时间为${this.delay}ms`); console.log('触发了click事件', e.target.value); this.count++; console.log(`触发了${this.count}次新增数据`); }, }, }; </script>
打印结果:
debounce wait时间为1000ms
触发了click事件
触发了1次新增数据
说明:快速点击2次“新增”按钮,而最终只触发了1次数据新增,达到了咱们的预期效果。
loading是指在异步请求完成(成功或者失败)前,开启loading,使得按钮或者用户界面处于“加载中”“转圈”“spin"这样的一个状态,从而禁止用户发起重复操做,异步请求完成后,关闭loading。
<template> <Button @click="loadingHandleClick" :loading="loading">新增</Button> </template> <script> export default { name: 'click-loading', data() { return { loading: false, count: 0, }; }, methods: { loadingHandleClick(e) { this.loading = true; this.count++; console.log(`触发了${this.count}次新增数据`); console.log('发起异步请求,loding为:', this.loading); setTimeout(() => { console.log('异步请求执行了1s'); this.loading = false; console.log('异步请求完成,loding为:', this.loading); }, 1000); }, }, }; </script>
触发了1次新增数据
发起异步请求,loding为: true
异步请求执行了1s
异步请求完成,loding为: false
说明:第1次事件触发后,按钮处于loading为true状态,禁止用户触发,1秒后异步请求执行完成,loading为false,容许用户再次使用。所以都没法作到快速点击2次“新增”按钮,只能触发1次,重复的第2次触发用户没法触发,最终只触发了1次数据新增,达到了咱们的预期效果。
地址:http://demo.nimius.net/deboun...
图片:
经过在canvas上连续触发mousemove事件咱们发现:
期待和你们交流,共同进步,欢迎你们加入我建立的与前端开发密切相关的技术讨论小组:
- SegmentFault技术圈:ES新规范语法糖
- SegmentFault专栏:趁你还年轻,作个优秀的前端工程师
- 知乎专栏:趁你还年轻,作个优秀的前端工程师
- Github博客: 趁你还年轻233的我的博客
- 前端开发QQ群:660634678
- 微信公众号: 人兽鬼 / excellent_developers
努力成为优秀前端工程师!