vue项目使用lodash节流防抖函数问题与解决

背景

在lodash函数工具库中,防抖_.debounce和节流_.throttle函数在一些频繁触发的事件中比较常用。

防抖函数_.debounce(func, [wait=0], [options=])

创建一个 debounced(防抖动)函数,该函数会从上一次被调用后,延迟 wait 毫秒后调用 func 方法。

参数

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

返回

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

节流函数_.throttle(func, [wait=0], [options=])

创建一个节流函数,在 wait 毫秒内最多执行 func 一次的函数。

参数

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

返回

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

在vue中使用防抖节流函数的问题

踩坑1

防抖节流函数实际上起到一个"稀释"的作用,在vue项目中我们可能会这样写(节流为例)。

html 复制代码
<template>
    <div>
        <button @click="add_throttle">加1</button>
        <h1>{{ number }}</h1>
    </div>
</template>

<script>
import { throttle } from 'lodash';
export default {
    data() {
        return {
            number: 1
        };
    },
    methods: {
        // add函数做节流处理
        add_throttle: throttle(this.add, 1000),
        add() {
            this.number++;
        }
    },
};
</script>

然后我们信心满满地F12打开控制台......

上面说add 这玩意儿 undefined了。

这其实是this的指向问题。实际上这里的this并不是vue实例(至于是什么,往下看你就知道了[doge]),所以自然不存在add()方法了。

踩坑2

既然直接使用this.add() 不成,那我们换个思路,把this.add()放在函数里呢?

jsx 复制代码
methods: {
    // 做节流处理
    add_throttle: throttle(() => {
        this.add();
    }, 1000),
    add() {
        this.number++;
    }
}

然后,自信满满地再次打开控制台......

第一眼,诶,没报错,于是点击按钮......

梅开二度......

其实还是this的指向问题。我们知道箭头函数是没有this的,所以这里的this相当于踩坑1里的this ,让我们打印下,揭开它的庐山真面目。

jsx 复制代码
methods: {
    // 做节流处理
    add_throttle: throttle(() => {
        console.log(this);
    }, 1000),
    add() {
        this.number++;
    }
}

好家伙,原来这里的this本身就是undefined

解决

既然是this的指向问题,那么只要保证this指向vue实例就行了,箭头函数换成声明式函数。

jsx 复制代码
methods: {
    // 做节流处理
    add_throttle: throttle(function () {
        this.add();
    }, 1000),
    add() {
        this.number++;
    }
}

结果很nice。

至于为什么,大概是lodash的_.debounce函数对this做了一些处理(_.throttle函数本质还是调用了_.debounce函数),有兴趣的小伙伴儿可以看看_.debounce的源码。

相关推荐
知识分享小能手9 小时前
微信小程序入门学习教程,从入门到精通,微信小程序核心 API 详解与案例(13)
前端·javascript·学习·react.js·微信小程序·小程序·vue
小灰灰的可爱无人可替代9 小时前
记录一次使用docker和docker-compose更新vue前端项目问题
nginx·docker·vue
java水泥工2 天前
酒店客房管理系统|基于SpringBoot和Vue的酒店客房管理系统(源码+数据库+文档)
spring boot·vue·酒店管理系统·酒店客房管理系统
爱看书的小沐3 天前
【小沐学WebGIS】基于Three.JS绘制飞行轨迹Flight Tracker(Three.JS/ vue / react / WebGL)
javascript·vue·webgl·three.js·航班·航迹·飞行轨迹
知识分享小能手4 天前
微信小程序入门学习教程,从入门到精通,WXS语法详解(10)
前端·javascript·学习·微信小程序·小程序·vue·团队开发
知识分享小能手5 天前
微信小程序入门学习教程,从入门到精通,WXSS样式处理语法基础(9)
前端·javascript·vscode·学习·微信小程序·小程序·vue
sniper_fandc5 天前
Vue3双向数据绑定v-model
前端·vue
知识分享小能手5 天前
微信小程序入门学习教程,从入门到精通,WXML(WeiXin Markup Language)语法基础(8)
前端·学习·react.js·微信小程序·小程序·vue·个人开发
叫兽~~6 天前
vite vue 打包后运行,路由首页加载不出来
vue.js·vue
岁岁岁平安7 天前
SpringBoot3+WebSocket+Vue3+TypeScript实现简易在线聊天室(附完整源码参考)
java·spring boot·websocket·网络协议·typescript·vue