问题
以前在开发小程序项目时,经常遇到节流需求,然后研究了好久都没成功。今天又遇到了,终于被我弄成功了。原来是使用方法错误,终究还是Javascript
的基本功差导致的。
使用的小程序开发框架是
mpvue
和uniapp
试错历程
做了很多尝试都没成功,但我觉得我这些错误的尝试方法有助于帮助我去理解这个问题,就记录下。
1. 试错案例一
<template>
<input type="digit" @input="onInput" />
<template>
<script>
import _lodash from '@/utils/myLodash'
export default {
data() {
value: { input: '' }
},
methods: {
onInput(e) {
_loadash.throttle(() => {
this.$set(this.value, 'input', e.value)
}, 1000)
}
}
}
</script>
这样的写法是无效的,后面研究了许久,其实节流函数throttle
本身就会返回一个匿名函数,所以就知道这种写法无效的原因了,尝试改进。
2. 试错案例二
<template>
<input type="digit" @input="onInput" />
<template>
<script>
import _lodash from '@/utils/myLodash'
export default {
data() {
value: { input: '' }
},
methods: {
onInput: _lodash.throttle(e => {
this.$set(this.value, 'input', e.value)
}, 1000)
}
}
</script>
经过这一番改进后,节流函数确实生效了,但是又出现了新的问题,会报如下错误:
TypeError: _this.$set is not a function
看到这个错误的时候我就知道这是this
绑定的作用域错误的问题导致的。后面我去翻看Lodash
源码发现throttle
函数有对我传入的回调函数进行apply
(绑定作用域)处理:
源码:
result = func.apply(thisArg, args)
// func就是我们传入的回调函数
此时我就明白了,箭头函数使用apply
是无效的,然后我把箭头函数改成了匿名函数就可以了。
想了解this
作用域问题的朋友可以参考我的另一篇文章:《ES5中,this永远指向最后调用它的那个对象》
注意: Vue官方文档中有提示
methods
中的函数不能使用箭头函数
最终解决方法
<template>
<input type="digit" @input="onInput" />
<template>
<script>
import _lodash from '@/utils/myLodash'
export default {
data() {
value: { input: '' }
},
methods: {
onInput: _lodash.throttle(function(e) {
this.$set(this.value, 'input', e.value)
}, 1000)
}
}
</script>