防抖(节流)函数在Vue项目中的应用。
文章目录防抖函数应用方式一:直接import到每个组件单独使用应用方式二:函数式组件实现防抖。应用方法三:使用自定义指令封装防抖函数。防抖函数废话少说,先上一个防抖函数。关键是如何应用到vue项目中。/*** @desc 函数防抖* @param func 函数* @param wait 延迟执行毫秒数* @param immediate true 表立即执行,false...
防抖函数
废话少说,先上一个防抖函数。
关键是如何应用到vue项目中。
/**
* @desc 函数防抖
* @param func 函数
* @param wait 延迟执行毫秒数
* @param immediate true 表立即执行,false 表非立即执行
*/
export function debounce (func, wait, immediate = true) {
let timeout
return function () {
if (timeout) clearTimeout(timeout)
if (immediate) {
var callNow = !timeout
timeout = setTimeout(() => {
timeout = null
}, wait)
if (callNow) func.apply(this, arguments)
} else {
timeout = setTimeout(function () {
func.apply(context, args)
}, wait)
}
}
}
应用方式一:直接import到每个组件单独使用
1、在每个需要应用debounce 函数的组件中,import导入debounce 函数,
2、然后在methods中,使用debounce函数封装一下目标函数。比如这里我们的目标是执行clickTest方法,要么直接将clickTest方法中的操作放到debounce函数的回调函数中执行,要么直接将整个clickTest方法放进来执行。
需要注意的是,这里debounce函数中的回调函数,一定不能写成箭头函数的形式(我知道你们es6玩得666),因为箭头函数绑定this,导致this为undefined。写成普通函数就可以直接调用vue实例中的方法了。
methods: {
debounceClickTest: debounce(function () {
this.clickTest()
}, 1000),
clickTest () {
console.log(this.form.uname, this.form.upwd)
}
}
3、最后在html部分直接调用debounceClickTest,
这种方法,并不推荐使用。除非项目中只有极个别地方,需要应用防抖。而且除非是一开始就按照这样处理,否则等项目写完了,还得一个个的将需要应用防抖的函数包裹到debounce函数中,对项目代码的破坏性太大。
应用方式二:函数式组件实现防抖。
1、debounce.js
import Vue from 'vue'
const debounce = (func, time, ctx, immediate = true) => {
let timeout
return function (...params) {
if (timeout) clearTimeout(timeout)
if (immediate) {
var callNow = !timeout
timeout = setTimeout(() => {
timeout = null
}, time)
if (callNow) func.apply(ctx, params)
} else {
timeout = setTimeout(function () {
func.apply(ctx, params)
}, time)
}
}
}
Vue.component('Debounce', {
abstract: true,
props: ['time', 'events', 'immediate'],
created () {
this.eventKeys = this.events && this.events.split(',')
this.originMap = {}
this.debouncedMap = {}
},
render () {
const vnode = this.$slots.default[0]
// 如果默认没有传 events,则对所有绑定事件加上防抖
if (!this.eventKeys) {
this.eventKeys = Object.keys(vnode.data.on)
}
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, vnode, this.immediate)
vnode.data.on[key] = this.debouncedMap[key]
}
})
return vnode
}
})
Debounce组件可以接受time,events,immediate 这3个参数,其中time是必填的,events和immediate是选填的。
events不填则默认所有事件应用防抖。
immediate不填,则默认为true,即立即执行再防抖。
在render函数中,Debounce组件修改了子VNode的事件,再将其返回回去。
再看看组件的应用方法,先在main.js中引入
import '@/functionComponent/debounce'
然后在需要应用防抖组件的位置,直接使用函数式组件。
<Debounce :time="1000">
<button @click="func_component_test">函数式组件防抖测试</button>
</Debounce>
<Debounce :time="1000" events="click">
<button @click="func_component_test">函数式组件防抖测试</button>
</Debounce>
<Debounce :time="1000" events="click" :immediate="false">
<button @click="func_component_test">函数式组件防抖测试</button>
</Debounce>
参考链接:
Vue实现函数防抖组件 https://juejin.im/post/5c2dc7a9e51d4573c8491e77#heading-0
不过这种方法,还是觉得稍显麻烦。如果多个位置应用防抖,那么就需要写非常多处<debounce></debounce>组件,但是对于学习函数式组件来说确实是一个不错的思路。
应用方法三:使用自定义指令封装防抖函数。
本次项目中,使用的就是这种方法。通过注册全局自定义指令,在需要应用防抖的地方,替换掉@click,这样对代码的修改比较少。
directive.js
import Vue from 'vue'
import { debounce } from '@/utils/common'
// 防抖自定义指令
Vue.directive('debounce', {
bind (el, binding) {
const executeFunction = debounce(binding.value, 1000)
el.addEventListener('click', executeFunction)
}
})
应用结果
<button v-debounce="login">登陆</button>
<br>
<button v-debounce="getCount">自定义指定防抖测试</button>
节流函数的应用方式同理,这里就不赘述。
更多推荐
所有评论(0)