夜猫子的知识栈 夜猫子的知识栈
首页
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript教程》
    • 《Web Api》
    • 《ES6教程》
    • 《Vue》
    • 《React》
    • 《TypeScript》
    • 《Git》
    • 《Uniapp》
    • 小程序笔记
    • 《Electron》
    • JS设计模式总结
  • 《前端架构》

    • 《微前端》
    • 《权限控制》
    • monorepo
  • 全栈项目

    • 任务管理日历
    • 无代码平台
    • 图书管理系统
  • HTML
  • CSS
  • Nodejs
  • Midway
  • Nest
  • MySql
  • 其他
  • 技术文档
  • GitHub技巧
  • 博客搭建
  • Ajax
  • Vite
  • Vitest
  • Nuxt
  • UI库文章
  • Docker
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

夜猫子

前端练习生
首页
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript教程》
    • 《Web Api》
    • 《ES6教程》
    • 《Vue》
    • 《React》
    • 《TypeScript》
    • 《Git》
    • 《Uniapp》
    • 小程序笔记
    • 《Electron》
    • JS设计模式总结
  • 《前端架构》

    • 《微前端》
    • 《权限控制》
    • monorepo
  • 全栈项目

    • 任务管理日历
    • 无代码平台
    • 图书管理系统
  • HTML
  • CSS
  • Nodejs
  • Midway
  • Nest
  • MySql
  • 其他
  • 技术文档
  • GitHub技巧
  • 博客搭建
  • Ajax
  • Vite
  • Vitest
  • Nuxt
  • UI库文章
  • Docker
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 基础

  • 响应式

  • 组件

  • 过渡&动画

  • 可复用性

  • 工具

  • 规模化

  • 路由

  • 组合式

  • Vuex

  • Pinia

  • 其他

    • 实现动态toast
    • 手动渲染虚拟dom
    • 全局事件总线($bus)
    • 全局方法和属性 createAPP
    • Vue3-TS 中使用 Express
    • watch监听Props属性值失败原因
    • main.js推荐配置
    • 脚手架前期基础配置
    • 跨域之config.js配置
    • Vue中的防抖函数封装和使用
      • vue的数据更新
      • 操作本地缓存
      • api使用流程
      • ajax封装及api的获取和配置
      • vue解析n字符
      • TS获取ref绑定元素
      • 解决vue3中Props无法引入外部类型
      • vue2升vue3注意事项
    • Vue3 源码学习记录

    • 《Vue》笔记
    • 其他
    夜猫子
    2020-02-04
    目录

    Vue中的防抖函数封装和使用

    # Vue 中的防抖函数封装和使用

    如搜索框中,每改变一个数值就请求一次搜索接口,当快速的改变数值时并不需要多次请求接口,这就需要一个防抖函数:

    function debounce(func, wait, options) {
      let lastArgs, lastThis, maxWait, result, timerId, lastCallTime;
    
      let lastInvokeTime = 0;
      let leading = false;
      let maxing = false;
      let trailing = true;
    
      // Bypass `requestAnimationFrame` by explicitly setting `wait=0`.
      const useRAF =
        !wait &&
        wait !== 0 &&
        window &&
        typeof window.requestAnimationFrame === 'function';
    
      if (typeof func !== 'function') {
        throw new TypeError('Expected a function');
      }
      wait = +wait || 0;
      if (options && typeof options === 'object') {
        leading = !!options.leading;
        maxing = 'maxWait' in options;
        maxWait = maxing ? Math.max(+options.maxWait || 0, wait) : maxWait;
        trailing = 'trailing' in options ? !!options.trailing : trailing;
      }
    
      function invokeFunc(time) {
        const args = lastArgs;
        const thisArg = lastThis;
    
        lastArgs = lastThis = undefined;
        lastInvokeTime = time;
        result = func.apply(thisArg, args);
        return result;
      }
    
      function startTimer(pendingFunc, wait) {
        if (useRAF) {
          window.cancelAnimationFrame(timerId);
          return window.requestAnimationFrame(pendingFunc);
        }
        return setTimeout(pendingFunc, wait);
      }
    
      function cancelTimer(id) {
        if (useRAF) {
          return window.cancelAnimationFrame(id);
        }
        clearTimeout(id);
      }
    
      function leadingEdge(time) {
        // Reset any `maxWait` timer.
        lastInvokeTime = time;
        // Start the timer for the trailing edge.
        timerId = startTimer(timerExpired, wait);
        // Invoke the leading edge.
        return leading ? invokeFunc(time) : result;
      }
    
      function remainingWait(time) {
        const timeSinceLastCall = time - lastCallTime;
        const timeSinceLastInvoke = time - lastInvokeTime;
        const timeWaiting = wait - timeSinceLastCall;
    
        return maxing
          ? Math.min(timeWaiting, maxWait - timeSinceLastInvoke)
          : timeWaiting;
      }
    
      function shouldInvoke(time) {
        const timeSinceLastCall = time - lastCallTime;
        const timeSinceLastInvoke = time - lastInvokeTime;
    
        // Either this is the first call, activity has stopped and we're at the
        // trailing edge, the system time has gone backwards and we're treating
        // it as the trailing edge, or we've hit the `maxWait` limit.
        return (
          lastCallTime === undefined ||
          timeSinceLastCall >= wait ||
          timeSinceLastCall < 0 ||
          (maxing && timeSinceLastInvoke >= maxWait)
        );
      }
    
      function timerExpired() {
        const time = Date.now();
        if (shouldInvoke(time)) {
          return trailingEdge(time);
        }
        // Restart the timer.
        timerId = startTimer(timerExpired, remainingWait(time));
      }
    
      function trailingEdge(time) {
        timerId = undefined;
    
        // Only invoke if we have `lastArgs` which means `func` has been
        // debounced at least once.
        if (trailing && lastArgs) {
          return invokeFunc(time);
        }
        lastArgs = lastThis = undefined;
        return result;
      }
    
      function cancel() {
        if (timerId !== undefined) {
          cancelTimer(timerId);
        }
        lastInvokeTime = 0;
        lastArgs = lastCallTime = lastThis = timerId = undefined;
      }
    
      function flush() {
        return timerId === undefined ? result : trailingEdge(Date.now());
      }
    
      function pending() {
        return timerId !== undefined;
      }
    
      function debounced(...args) {
        const time = Date.now();
        const isInvoking = shouldInvoke(time);
    
        lastArgs = args;
        lastThis = this;
        lastCallTime = time;
    
        if (isInvoking) {
          if (timerId === undefined) {
            return leadingEdge(lastCallTime);
          }
          if (maxing) {
            timerId = startTimer(timerExpired, wait);
            return invokeFunc(lastCallTime);
          }
        }
        if (timerId === undefined) {
          timerId = startTimer(timerExpired, wait);
        }
        return result;
      }
      debounced.cancel = cancel;
      debounced.flush = flush;
      debounced.pending = pending;
      return debounced;
    }
    
    // 节流函数
    /**
     * @param {Function} func
     * @param {number} wait
     * @param {boolean} immediate
     * @return {*}
     */
    export function throttle(func, wait, immediate) {
      let timeout, context, args, result;
      let previous = 0;
    
      const later = function() {
        previous = immediate ? 0 : +new Date();
        timeout = null;
        result = func.apply(context, args);
        if (!timeout) context = args = null;
      };
    
      return function(...params) {
        const now = +new Date();
        context = this;
        args = params;
        
        if (!previous && immediate) previous = now;
        
        // 距离下次执行还需要等待多长时间
        const remaining = wait - (now - previous);
    
        if (remaining <= 0 || remaining > wait) {
          if (timeout) {
            clearTimeout(timeout);
            timeout = null;
          }
          previous = now;
          result = func.apply(context, args);
          if (!timeout) context = args = null;
        } else if (!timeout) {
          timeout = setTimeout(later, remaining);
        }
        
        return result;
      };
    }
    
    function throttle(func, wait, options) {
      let leading = true;
      let trailing = true;
    
      if (typeof func !== 'function') {
        throw new TypeError('Expected a function');
      }
      if (options && typeof options == 'object') {
        leading = 'leading' in options ? !!options.leading : leading;
        trailing = 'trailing' in options ? !!options.trailing : trailing;
      }
      return debounce(func, wait, {
        leading,
        trailing,
        maxWait: wait,
      });
    }
    
    
    //使用:
    const submitForm = debounce(() => {
      getFileUrl().then(() => {
        feedback(Object.assign({}, formData)).then(() => {
          ifSubmitback.value = true;
        });
      });
    }, 500);
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221

    # 相关文章

    防抖与节流函数 (opens new window)

    编辑 (opens new window)
    #Vue
    上次更新: 2026/4/20 16:35:10
    跨域之config.js配置
    vue的数据更新

    ← 跨域之config.js配置 vue的数据更新→

    最近更新
    01
    多件折加购功能
    09-23
    02
    店铺收款信息变更审核
    09-22
    03
    店铺入驻需求
    09-20
    更多文章>
    Copyright © 2019-2026 Study | MIT License
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式