Vue中如何将绑定的带参事件回调函数转换为节流或者防抖

本文详细介绍了如何在Vue中将带有参数的click事件回调函数转换为lodash的throttle和debounce节流和防抖版本,包括函数形式的调整、异步处理和参数传递技巧。重点讲解了如何在实际场景中应用这些技术来优化性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

函数定义

lodash 中的节流函数throttle和防抖函数debounce官方文档是这样定义的:

_.throttle(func, [wait=0], [options=])

参数

func (Function): 要节流的函数。
[wait=0] (number): 需要节流的毫秒。
[options=] (Object): 选项对象。
[options.leading=true] (boolean): 指定调用在节流开始前。
[options.trailing=true] (boolean): 指定调用在节流结束后。

返回

(Function): 返回节流的函数。

_.debounce(func, [wait=0], [options=])

参数

func (Function): 要防抖动的函数。
[wait=0] (number): 需要延迟的毫秒数。
[options=] (Object): 选项对象。
[options.leading=false] (boolean): 指定在延迟开始前调用。
[options.maxWait] (number): 设置 func 允许被延迟的最大值。
[options.trailing=true] (boolean): 指定在延迟结束后调用。

返回

(Function): 返回新的 debounced(防抖动)函数。

现实需求

把一个带参数的函数转化为节流和防抖版本的,如何保证传参可行。在使用Vue开发时,如何转换节流和防抖函数。现有的情形描述一下就是,有个button的click事件,目前click事件的回调函数是带参数的,而且参数不能省,如何将这个回调函数转换为节流或者防抖版本的。

<el-button @click="handleOnSale(scope.row)"/>
async handleOnSale(row) {
 if (row.isOnShelf === 0) {
    try {
      await this.$confirm('确定要上架吗?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      })
    } catch (e) {
      console.log(e)
      return
    }
    try {
      const topic = Object.assign({}, { isOnShelf: 1, topicKey: row.topicKey })
      const res = await this.$api.knowledge.updateTopic(topic)
      if (res && res.code === 0) {
        this.$message({
          message: '上架成功',
          type: 'success'
        })
        setTimeout(() => {
          this.pagination.current = 1
          this.tableReload(this.formSearch)
        }, 2000)
      }
    } catch (e) {
      console.log(e)
    }
  }
  if (row.isOnShelf === 1) {
    try {
      await this.$confirm('确定要下架吗?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      })
    } catch (e) {
      console.log(e)
      return
    }
    try {
      const topic = Object.assign({}, { isOnShelf: 0, topicKey: row.topicKey })
      const res = await this.$api.knowledge.updateTopic(topic)
      if (res && res.code === 0) {
        this.$message({
          message: '下架成功',
          type: 'success'
        })
        setTimeout(() => {
          this.pagination.current = 1
          this.tableReload(this.formSearch)
        }, 2000)
      }
    } catch (e) {
      console.log(e)
    }
  }
},

理解节流和防抖函数的使用

要想使用节流或者防抖函数,需要传递一个纯函数,即不带参数的函数(其实是不带括号的函数),这里需要指出带参和不带参(不带括号)的区别:

function foo(){}
function bar(a,b){}
console.log(typeof foo) //function
console.log(typeof bar) //function
console.log(typeof bar(1,2)) //undefined

通过typeof运算,可以看出,如果一个函数是带参的,会判断为undefined,原理是函数本质是一个地址,函数调用是一个返回结果,如果一个函数带参(其实就是带括号了,参数没有都可以)了,会解释为函数调用,如果函数没有返回值,typeof就是undefined,如果有返回值,typeof就是返回值的类型

function bar(a,b){return false}
console.log(typeof bar(1,2)) //boolean

那如果函数必须要带参数,如何使用节流和防抖呢?

其实,只要传递函数名称就可以了,不要带参(带括号)就行了。譬如:

function bar(a,b){return false}
let throttleBar = _.throttle(bar,2000,{leading:true,trailing:false})
let debounceBar = _.debounce(bar,2000,{leading:true,trailing:false})

这样throttleBardebounceBar就是节流和防抖版本的bar函数了,调用时,

throttleBar(1,2)
debounceBar(1,2)

即可

Vue中如何对绑定的事件回调函数转换为节流或者防抖

正如我们现实情况遇到的,绑定的click事件回调函数,里面涉及异步操作,特别的我们使用了async语法,那么回调函数本质是一个promise function而不是function,而 _.throttle(func, [wait=0], [options=])、 _.debounce(func, [wait=0], [options=])都要求入参funcfunction,所以需要将promise function类型转换为function类型,为此可以想到这样做:

handleOnSaleFun(row) {
  this.handleOnSale(row)
},

另外,节流和防抖函数转换,需要提前转换,也就是在绑定回调函数时,回调函数需要提前转换为节流和防抖版本,否则节流和防抖不会生效。

探索1:

<el-button @click="_.debounce(handleOnSaleFun, 2000, { leading: true, trailing: false })"/>

这样的方式不行,因为参数必须要传递

探索2:

<el-button @click="_.debounce(handleOnSaleFun, 2000, { leading: true, trailing: false })(scope.row)"/>

这样也不行,事件绑定回调也是纯函数,不是函数调用

探索3:

<el-button @click="debounceHandleOnSaleFun(scope.row)"/>
computed: {
  debounceHandleOnSaleFun() {
    return _.debounce(this.handleOnSaleFun, 2000, { leading: true, trailing: false })
  }
},

利用计算属性得到一个防抖或者节流版本的函数,这样的函数其实就是纯函数,在事件的回调函数中,传递参数不会解释为函数调用,而是带参的函数,这样就实现了带参函数的防抖和节流。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值