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

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

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

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

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

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);
  };
};

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

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);
  },
});

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

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

html 复制代码
<button data-key="demoKey" bind:tap="dbClickHandler"></button>

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

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

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

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;
  };
}

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

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)
  }),
});

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

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

html 复制代码
<input id='address' placeholder="小区/写字楼/学校等" bindinput="throttleInputChange" />

END.

相关推荐
汪子熙14 分钟前
Angular 服务器端应用 ng-state tag 的作用介绍
前端·javascript·angular.js
Envyᥫᩣ22 分钟前
《ASP.NET Web Forms 实现视频点赞功能的完整示例》
前端·asp.net·音视频·视频点赞
applebomb1 小时前
【2024】uniapp 接入声网音频RTC【H5+Android】Unibest模板下Vue3+Typescript
typescript·uniapp·rtc·声网·unibest·agora
Мартин.4 小时前
[Meachines] [Easy] Sea WonderCMS-XSS-RCE+System Monitor 命令注入
前端·xss
昨天;明天。今天。6 小时前
案例-表白墙简单实现
前端·javascript·css
数云界6 小时前
如何在 DAX 中计算多个周期的移动平均线
java·服务器·前端
风清扬_jd6 小时前
Chromium 如何定义一个chrome.settingsPrivate接口给前端调用c++
前端·c++·chrome
安冬的码畜日常6 小时前
【玩转 JS 函数式编程_006】2.2 小试牛刀:用函数式编程(FP)实现事件只触发一次
开发语言·前端·javascript·函数式编程·tdd·fp·jasmine
ChinaDragonDreamer6 小时前
Vite:为什么选 Vite
前端
小御姐@stella6 小时前
Vue 之组件插槽Slot用法(组件间通信一种方式)
前端·javascript·vue.js