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

由于微信小程序与普通网页的开发、编译、运行机制都有所不同,在防抖节流的方法使用上也就需要我们做一些比较棘手的适配操作。常见的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.

相关推荐
Mintopia1 分钟前
3D Quickhull 算法:用可见性与冲突图搭建空间凸壳
前端·javascript·计算机图形学
白日依山尽yy1 分钟前
Vue、微信小程序、Uniapp 面试题整理最新整合版
vue.js·微信小程序·uni-app
Mintopia1 分钟前
Three.js 三维数据交互与高并发优化:从点云到地图的底层修炼
前端·javascript·three.js
新手小黑吖4 分钟前
vscode开发微信小程序
vscode·微信小程序
陌小路7 分钟前
5天 Vibe Coding 出一个在线音乐分享空间应用是什么体验
前端·aigc·vibecoding
成长ing1213815 分钟前
cocos creator 3.x shader 流光
前端·cocos creator
Alo36523 分钟前
antd 组件部分API使用方法
前端
BillKu26 分钟前
Vue3数组去重方法总结
前端·javascript·vue.js
GDAL28 分钟前
Object.freeze() 深度解析:不可变性的实现与实战指南
javascript·freeze
江城开朗的豌豆1 小时前
Vue+JSX真香现场:告别模板语法,解锁新姿势!
前端·javascript·vue.js