• 【微信小程序开发】小程序版的防抖节流应该怎么写


    由于微信小程序与普通网页的开发、编译、运行机制都有所不同,在防抖节流的方法使用上也就需要我们做一些比较棘手的适配操作。常见的H5开发的防抖节流此处就不再分享了,网上有太多的教程,或者直接问那群AI即可。

    OK,言归正传,直接上代码:

    一、防抖函数(TS版)及其使用案例

    1、文件:pages/utils/index.ts

    /**  
     * 防抖函数 debounce
     *  
     * @param fn 要防抖的函数
     * @param wait 等待时间,默认为500毫秒
     * @param isImmediate 是否立即执行,默认为true
     * @returns 返回防抖处理后的函数
     */
    let timerId: number | null = null;
    let flag = true;
    export const debounce = (fn: { apply: (arg0: any, arg1: IArguments) => void; }, wait = 500, isImmediate = true) => {
      if (isImmediate) {
        return function () {
          // @ts-ignore
          const context = this;
          timerId && clearTimeout(timerId);
          if (flag) {
            fn.apply(context, arguments);
            flag = false;
          }
          timerId = setTimeout(() => {
            flag = true;
          }, wait);
        };
      }
      return function () {
        // @ts-ignore 将当前上下文(this)赋值给 context  
        const context = this;
        timerId && clearTimeout(timerId);
        timerId = setTimeout(() => {
          fn.apply(context, arguments);
        }, wait);
      };
    };
    
    • 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

    2、文件:pages/views/demoPage/index.ts

    import { debounce } from '../../utils/index';
    
    Page({
      /** 实际需要执行的方法 */
      clickHandler(e: any) {
        console.log('[clickHandler] e.currentTarget.dataset >>>');
        console.log(e.currentTarget.dataset);
      },
    
      /**
      * 防抖处理后的方法
      * 说明一下:其实这个才是重点,debounce写完以后,怎么绑定到页面中是个大问题!
      * 再尝试多次后,得出以下正确使用方式!
      * 当然,如果有更好的写法,欢迎大家评论补充,感谢一起分享!
      */
      dbClickHandler(e) {
        debounce(this.clickHandler)(e);
      },
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    3、文件:pages/views/demoPage/index.wxml

    这个就正常的bind就行,需要稍微注意的就是要bind包裹了一层防抖函数的 dbClickHandler,如下:

    <button data-key="demoKey" bind:tap="dbClickHandler">button>
    
    • 1

    二、节流函数(TS版)及其使用案例

    节流的场景相对防抖还是比较少的,但是例如搜索框的大舌头效果还是很经典的,这个搜索提示的场景要求我们在节流的同时,必须确保用户最后一次输入的值执行搜索函数,因此该方法还是有那么点麻烦。

    1、文件:pages/utils/index.ts

    // 定义一个泛型类型 Func,代表任何接收任意参数并返回任意结果的函数  
    type Func = (...args: any[]) => any;
    /**  
     * 节流函数,用于限制给定函数的执行频率。  
     *  
     * @param fn 需要进行节流的函数。  
     * @param delay 函数执行之间的延迟时间,以毫秒为单位。默认为500毫秒。  
     * @returns 返回一个新函数,当调用该新函数时,会根据指定的延迟时间执行被节流的函数。  
     */
    export function throttle(fn: Func, delay = 500) {
      let lastFunc: any;
      let lastRan: number;
      let context: any;
      let args: any;
      let result: any;
    
      // 定义一个内部函数 executeFunc,用于实际执行传入的函数 fn 
      const executeFunc = function () {
        result = fn.apply(context, args);
        lastRan = Date.now();
        clearTimeout(lastFunc as any);
        lastFunc = null;
        context = null;
        args = null;
      };
    
      // 返回一个新的函数,该函数在被调用时会执行节流逻辑  
      return function () {
        // @ts-ignore 将当前上下文(this)赋值给 self  
        const self = this;
        context = self;
        args = arguments;
        const now = Date.now();
        if (!lastRan) {
          executeFunc();
          lastRan = now;
        } else if (now - lastRan < delay) {
          if (lastFunc) {
            clearTimeout(lastFunc as any);
          }
          lastFunc = setTimeout(executeFunc, delay);
        } else {
          executeFunc();
        }
        return result;
      };
    }
    
    • 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

    2、文件:pages/views/demoPage/index.ts

    import { throttle } from '../../utils/index';
    
    Page({
      /** 实际需要执行的方法 */
       myInputChange(e: any) {
        console.log('[myInputChange] doing...');
        console.log('[myInputChange] id:', e.target.id);
        console.log('[myInputChange] value:', e.detail.value);
      },
      
      /**
      * 节流处理后的方法
      * 注意:为了能成功用上节流这个方法,此处的写法也必须是这样类似选项式的写法
      */
      throttleInputChange: throttle(function(e) {
        console.log('[throttleInputChange] doing...');
        // @ts-ignore
        this.myInputChange(e)
      }),
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    3、文件:pages/views/demoPage/index.wxml

    以下是一个地址搜索框的例子,还是注意下bind包裹后的节流函数throttleInputChange即可。

    <input id='address' placeholder="小区/写字楼/学校等" bindinput="throttleInputChange" />
    
    • 1

    END.

  • 相关阅读:
    nbcio-boot如何进行gitee第三方登录
    一些SQL小技巧,不定期更新...
    Python爬虫的七个常用技巧总结,这些你一定得知道!
    Linux通过公网安装k8s集群
    【C语言】内存操作,内存函数篇---memcpy,memmove,memset和memcmp内存函数的使用和模拟实现【图文详解】
    腾讯云16核服务器配置有哪些?CPU型号处理器主频性能
    springcloud
    python 第四章面向对象
    基于Springboot+Vue+Element实现汽车租赁系统
    MySQL的架构和性能优化
  • 原文地址:https://blog.csdn.net/fifteen718/article/details/136113397