防抖函数的封装请看前端面试题(js):手写防抖节流?
在一个防抖操作中,内部timer变量需要被一直保存 -> 封装防抖函数时使用闭包 -> 使用防抖函数时,用一个变量引用包含闭包的函数
1.防抖函数的核心:
声明的timer变量,且在一个防抖操作中,timer需要一直保存,不被销毁。
一般函数执行完,函数内部变量自动回收,如何做到timer不被销毁?
2.利用闭包,保存timer。
闭包的前提:函数嵌套,且内层函数对外层函数的变量有引用。
闭包的生命周期:
1.产生:内部函数定义时产生,即外部函数被调用。
2.死亡:包含闭包的函数对象成为垃圾对象。
<body>
<!--
1. 产生: 在嵌套内部函数定义执行完时就产生了(不是在调用)
2. 死亡: 在嵌套的内部函数成为垃圾对象时
-->
<script type="text/javascript">
function fn1() {
//此时闭包就已经产生了(函数提升, 内部函数对象已经创建了)
var a = 2
function fn2 () {
a++
console.log(a)
}
return fn2
}
var f = fn1()
f() // 3
f() // 4
f = null //闭包死亡(包含闭包的函数对象成为垃圾对象)
</script>
</body>
3.在vue中,如何使用一个变量,保存对包含闭包的函数的引用?
使用场景一:直接声明变量,引用防抖函数(包含闭包的函数)
使用场景二:在钩子函数中声明变量引用防抖函数(包含闭包的函数),这个目前还没搞懂。
以下代码,可以看到mounted内部又产生一个闭包,保存了refresh,refresh引用了防抖函数(包含闭包的函数)。盲猜vue实例引用了这个包含闭包(refresh)的函数对象,后续再做补充。

4.当前vue实例销毁时,清除对包含闭包的函数的引用,即清除闭包
当前vue实例销毁时,清除闭包。最初我是这样做的:
onUnload() { // beforeDestroyed
this.inputDebounce = null
},
即手动清对包含闭包的函数的引用。后来我想了下,当vue实例销毁时,当前vue实例内部的变量被销毁了吗,那我还需要手动清除吗?后续再做补充。
5.实际使用
防抖函数已在utils文件夹下封装好,于是我在uni-app项目中用了下,有两种方法:(vue同理)
法一:
<template>
<view>
<view class="search-box">
<uni-search-bar @input="inputDebounce" placeholder="请输入搜索内容" radius="18" cancelButton="none" focus="always"/>
</view>
</view>
</template>
<script>
import { debounce } from '@/utils'
export default {
data() {
return {
};
},
methods: {
searchInput(e) {
console.log(e)
},
inputDebounce: debounce(function(e) { //这里的inputDebounce引用了防抖函数
this.searchInput(e)
})
},
onUnload() {
this.inputDebounce = null
console.log(this.inputDebounce)
},
}
</script>
法二:
<template>
<view>
<view class="search-box">
<uni-search-bar @input="inputDebounce" placeholder="请输入搜索内容" radius="18" cancelButton="none" focus="always"/>
</view>
</view>
</template>
<script>
import { debounce } from '@/utils'
export default {
data() {
return {
inputDebounce: debounce(function(e) { //这里的inputDebounce引用了防抖函数
this.searchInput(e)
})
};
},
methods: {
searchInput(e) {
console.log(e)
},
},
onUnload() {
this.inputDebounce = null
console.log(this.inputDebounce)
},
}
</script>
如有错误,欢迎指正
|