防抖
定义:当一段时间内连续多次触发某事件时,只执行最后一次。如果在设置的间隔时间内又触发事件,则清除定时器重新计时。
案例:持续触发 scroll 事件时,不立即执行 handle 函数,当 1s 内没有再触发 click 事件时才执行 handle
代码:
用 addEventListener 添加防抖
created() {
window.addEventListener('resize', this.debounce(this.fn, 500))
},
methods: {
debounce (fn, wait) {
let timer = null
return () => {
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(fn, wait)
}
},
fn () {
console.log(Math.random())
}
}
复制代码
用 onClick 添加防抖
没有闭包,定时器也是唯一的,只能给一个按钮添加防抖
闭包的好处:不产生全局变量,可以复用
// 防抖方法从外面引入
<el-button @click="debounce(fn, 1000)">test</el-button>
// utils.js
Vue.prototype.debounce = function (fn, wait) {
if (window.timer2) {
clearTimeout(window.timer2)
}
window.timer2 = setTimeout(fn, wait)
}
// 防抖的方法在当前文件内
<el-button @click="debounce(fn, 1000)">test</el-button>
debounce (fn, wait) {
if (this.timer) {
clearTimeout(this.timer)
}
this.timer = setTimeout(fn, wait)
},
fn () {
console.log(Math.random())
}
复制代码
闭包形式的:
// 防抖的方法从外面引入
Vue.prototype.yyy = (fn, delay = 1000) => {
let timer = null
return (...params) => {
const context = this
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(() => {
fn.apply(context, params)
}, delay)
}
}
created() {
this.zzz = this.yyy(this.fn)
}
<el-button @click="zzz(1)">test</el-button>
// 防抖的方法在当前页面内
// 给闭包传 fn 传不进去,是 undefined
复制代码
重点是要拿到 debounce 方法返回的那个 方法A,绑定事件的时候要绑定这个 方法A。
推荐使用方式:
- 在外面用闭包形式写防抖,然后引入
- 全局指令形式
全局指令形式具体代码:
directive/debounce.js
import { debounce } from '@/utils'
export default {
inserted: function(el, binding, vnode) {
let [fn,wait,immediate,event = "click"] = binding.value
el.addEventListener(event, debounce(
fn,
wait,
immediate
).bind(vnode))
}
}
复制代码
directive/index.js
import debounce from './debounce'
const install = function (Vue) {
Vue.directive('debounce', debounce)
}
debounce.install = install
export {
debounce
}
复制代码
main.js
import {debounce} from './directive'
debounce.install(Vue)
复制代码
Test.vue
<el-button v-debounce="[fn]">test</el-button>
fn () {
console.log(Math.random())
}
复制代码
节流
定义:当一段时间内连续多次触发某事件时,每个间隔时间内只能执行一次,过了间隔时间才能执行下一次。
案例:持续触发 scroll 事件时,不立即执行 handle 函数,每个 1s 执行一次 handle。
代码:
export const throttle = (fn: Function, delay = 2000) => {
let preTime = Date.now()
return (...params: any[]) => {
const context = this
let doTime = Date.now()
if (doTime - preTime >= delay) {
fn.apply(context, params)
preTime = Date.now()
}
}
}