节流和防抖vue中使用
- 防抖:你点击那一下开始,如果你继续没有停止还在继续的疯狂的点击,他就给你执行一次,直到你停止为了,然后再次点击就会执行第二次
- 节流:你点击那一下开始,如果你继续没有停止还在继续的疯狂的点击,超过你指定的时间就继续执行第二次
防抖(debounce)
- 触发高频事件后n秒内函数只会执行一次,如果在n秒内高频事件再次被触发,则重新计算时间。
简单的说也就是一定时间段的无论点击多少次,只会执行最后一次的调用。前面的会被清除
- 在methods中直接实现
debounce (func, delay = 1000, immediate = false) {
//闭包
let timer = null
//不能用箭头函数
return function () {
if (timer) {
clearTimeout(timer)
}
if (immediate && !timer) {
func.apply(this,arguments)
}
timer = setTimeout(() => {
func.apply(this,arguments)
}, delay)
}
},
- 在
vue
中引入使用
<template>
<el-input v-model="text" @input="debounceInput" />
</template>
<script>
export default {
mounted () {
this.debounceInput = this.debounce(this.handle, 1000,false)
},
data () {
return {
text: '',
debounceInput: () => {},
}
},
methods: {
handle (value) {
console.log(value)
},
debounce (func, delay = 1000, immediate = false) {
let timer = null
//不能用箭头函数
return function () {
//在时间内重复调用的时候需要清空之前的定时任务
if (timer) {
clearTimeout(timer)
}
//适用于首次需要立刻执行的
if (immediate && !timer) {
func.apply(this,arguments)
}
timer = setTimeout(() => {
func.apply(this,arguments)
}, delay)
}
},
}
}
</script>
节流(throttle)
- 触发高频事件后,但在
n
秒内函数只会执行一次
简单的说也就是一定时间内的无论点击多少次,都只会执行第一次,其余的直接
return
- 在
utils.js
中实现(时间戳版本)
export const throttle = (fn, delay = 1000) => {
//距离上一次的执行时间
let lastTime = 0
return function () {
let _this = this
let _arguments = arguments
let now = new Date().getTime()
//如果距离上一次执行超过了delay才能再次执行
if(now - lastTime > delay){
fn.apply(_this,_arguments)
lastTime = now
}
}
}
- 在
vue
中引入使用
<template>
<el-input v-model="text" @input="throttleInput" />
</template>
<script>
import {throttle} from '../utils'
export default {
name: 'throttle',
data () {
return {
text: '',
}
},
methods: {
handle (value) {
console.log(value)
},
throttleInput: throttle(function (...args) {
this.handle(...args)
})
}
}
</script>
节流的优化
上一次执行和下一次用户操作的时间差在
delay
内的话,这个操作就会被废弃,所以我们需要在这个时间段内生成一个timer
去保证这个操作是会执行的,如果超过delay时间的话可以直接执行
- 在
utils.js
中
export const throttle = (fn, delay = 2000) => {
let lastTime = 0, timer = null
return function () {
let _this = this
let _arguments = arguments
let now = new Date().getTime()
clearTimeout(timer)
// 判断上次触发的时间和本次触发的时间差是否小于delay,创建一个timer
if (now - lastTime < delay) {
timer = setTimeout(function () {
lastTime = now
console.log("执行器触发")
fn.apply(_this, _arguments)
}, delay)
} else {
// 否则可以直接执行
lastTime = now
console.log("直接触发")
fn.apply(_this, _arguments)
}
}
}
另外一种
- 用法差不多
仅参考
// 在utils.js中
export const debout = function throttle(fn, time) {
//节流函数
var last = 0
return function () {
var now = new Date().getTime()
if (now - last >= time) {
last = now
fn.apply(this, arguments)
}
}
}
// 在vue中引入使用
// 在methods中直接实现
throttleInput: debout(function (...args) {
this.sub(...args)
}, 2000),
第三方库对节流和防抖的实现(lodash)🔨
- 安装
lodash
# npm
npm install lodash --save
#yarn
yarn add lodash
Vue中使用节流和防抖例子
throttling
方法 节流
要对事件进行节流处理方法非常简单,只需将要调用的函数包装在
lodash
的_.throttle
函数中即可。
<template>
<button @click="throttledMethod()">Click me as fast as you can!</button>
</template>
<script>
import _ from 'lodash'
export default {
methods: {
// vue中的methods中声明,左侧变量,右侧函数的形式声明, 点击的时候触发,因为throttle返回的是一个函数。函数调用必须用 ()调用
throttledMethod: _.throttle(() => {
console.log('I get fired every two seconds!')
},
2000,
{
leading: true,
trailing: false,
}
),
}
}
</script>
- throttle API走起
_.throttle(func, [wait=0], [options={}])
func (Function)
: 要节流的函数。
[wait=0] (number)
: 需要节流的毫秒数。
[options={}] (Object)
: 选项对象。
[options.leading=true] (boolean)
: 指定调用在节流开始前,默认true
。
[options.trailing=true] (boolean)
: 指定调用在节流结束后,默认true
。
debouncing
方法 防抖
尽管节流在某些情况下很有用,但一般情况我们经常使用的是防抖。 防抖实质上将我们的事件分组在一起,并防止它们被频繁触发。 要在
Vue
组件中使用节流,只需将要调用的函数包装在lodash
的_.debounce
函数中。
<template>
<button @click="throttledMethod()">Click me as fast as you can!</button>
</template>
<script>
import _ from 'lodash'
export default {
methods: {
throttledMethod: _.debounce(() => {
console.log('I only get fired once every two seconds, max!')
},
2000,
{
leading: true,
trailing: false,
}
),
}
}
</script>
- debounce API走起
_.debounce(func, [wait=0], [options={}])
func (Function)
: 要防抖动的函数。
[wait=0] (number)
: 需要延迟的毫秒数。
[options={}] (Object)
: 选项对象。
[options.leading=false] (boolean)
: 指定在延迟开始前调用,默认false
。
[options.maxWait] (number)
: 设置func
允许被延迟的最大值。
[options.trailing=true] (boolean)
: 指定在延迟结束后调用,默认true
。
- 结合
element-ui
在查询中使用节流
<!-- 按钮 -->
<el-button @click="handleClick(item.event)">
点击
</el-button>
// 注意:使用lodash必须通过这种方式,throttle的箭头函数,里面的this反而为undefined
// 必须通过function(event),里面的this才是指向vue
handleClick: _.throttle(function(event) {
this.$emit("handleClick", event);
console.log("lodash");
},
4000,
{
leading: true,
trailing: false,
}
),
vue 防抖节流函数——组件封装 🚀
防抖(debounce)
所谓防抖,就是指触发事件后在
n
秒内函数只能执行一次,如果在n
秒内又触发了事件,则会重新计算函数执行时间。
节流(throttle)
所谓节流,就是指连续触发事件但是在
n
秒中只执行一次函数。节流会稀释函数的执行频率。
就相当于,一个水龙头在滴水,可能一次性会滴很多滴,但是我们只希望它每隔
500ms
滴一滴水,保持这个频率。即我们希望函数在以一个可以接受的频率重复调用。
vue
封装utils.js
const debounce = (func, time, isDebounce, ctx) => {
var timer, lastCall, rtn
//防抖函数
if (isDebounce) {
rtn = (...params) => {
if (timer) clearTimeout(timer)
timer = setTimeout(() => {
func.apply(ctx, params)
}, time)
}
} else {
//节流函数
rtn = (...params) => {
const now = new Date().getTime()
if (now - lastCall < time && lastCall) return
lastCall = now
func.apply(ctx, params)
}
}
return rtn
}
export default {
name: 'Debounce',
abstract: true,
props: {
time: {
type: Number,
default: 800,
},
events: {
type: String,
default: 'click',
},
isDebounce: {
type: Boolean,
default: false,
},
},
created() {
this.eventKeys = this.events.split(',')
this.originMap = {}
this.debouncedMap = {}
},
render() {
const vnode = this.$slots.default[0]
this.eventKeys.forEach(key => {
const target = vnode.data.on[key]
if (target === this.originMap[key] && this.debouncedMap[key]) {
vnode.data.on[key] = this.debouncedMap[key]
} else if (target) {
this.originMap[key] = target
this.debouncedMap[key] = debounce(target, this.time, this.isDebounce, vnode)
vnode.data.on[key] = this.debouncedMap[key]
}
})
return vnode
},
}
- 然后我们在
main.js
入口文件里面全局注册一下
import Debounce from '@/config/debounce'
Vue.component('Debounce',Debounce)
- 组件中使用方法
当是
isDebounce
时表示是防抖函数,!isDebounce
是节流函数,time
是执行时间间隔
<!--当是isDebounce时表示是防抖函数,!isDebounce是节流函数,time是执行时间间隔-->
<Debounce :time='1000' isDebounce>
<button @click='btn'>btn</button>
</Debounce>