美文网首页一个程序员
小程序多次点击最佳实践

小程序多次点击最佳实践

作者: 杀手Kira | 来源:发表于2018-11-05 16:52 被阅读43次

    多次点击

    小程序没有好的优化事件处理机制,导致重复点击会触发多次(当我们快速点击的时候会多次执行,比如点击加载更多,进入下一页面的时候都会出现异常,多次调用,页面也会多次进入,对于体验)

    问题来源:

    • 来参加小程序活动详情加载更多用户的时候遇到的

    使用 disabled

    disabled 的限制比较多,只有对于有button按钮和支持的 disabled 的组件可以使用,使用 disabled 的方式来阻止多次点击在调试工具上可以,但是手机上亲测的情况是还是会有多次点击的情况,主要是因为click事件有250ms的延时,也就是说点击click后会在200ms后执行。所以,使用这个方法在快速点击的情况下还是会出现这样的问题,而且现在的状态为不可点击所以还要解除限制(不是好的可选方案)

    配合使用 touch 事件

    data里面定义3个属性

    touchStartTime: 0, // 触摸开始时间
    touchEndTime: 0, // 触摸结束时间
    lastTapTime: 0 // 最后一次单击事件点击发生时间
    

    页面触发这3个事件

    <button
      type='primary'
      bindtap="newTapHandle"
      bindtouchstart="touchStart"
      bindtouchend="touchEnd"
    >
      配合touch事件
    </button>
    

    methods里面添加3个方法

    touchStart(e) {
      console.log(e)
      this.touchStartTime = e.timeStamp;
    },
    touchEnd(e) {
      console.log(e)
      this.touchEndTime = e.timeStamp;
    },
    newTapHandle(e) {
      console.log(e);
      // 控制点击事件在350ms内触发,加这层判断是为了防止长按时会触发点击事件
      if (this.touchEndTime - this.touchStartTime < 350) {
        // 当前点击的时间
        var currentTime = e.timeStamp;
        var lastTapTime = this.lastTapTime;
    
        // 更新最后一次点击时间
        this.lastTapTime = currentTime;
    
        // 如果两次点击时间在250毫秒内,则认为是多次事件
        if (currentTime - lastTapTime > 250) {
          // do something 点击事件具体执行那个业务
          console.log('双击')
          wx.navigateTo({
            url: '/pages/logs/logs',
          })
        }
      }
    },
    

    这个方法基本呢个解决我们需要的多次点击问题,通过touch时间的开始和结束的时间间隔,判断点击的状态,但是这个方法还是有个弊端,就是第一次快速点击的时候不会执行里面的方法,而且,要借助touch事件来完成,通用性很差,无疑增加了逻辑的复杂程度。

    函数截流

    为什么会有函数截流?
    在前端 JS 在处理 DOM 的 scroll resize mousemove 等事件会不间断触发。以 scroll 事件为例:

    const scrollFn = () => {
        console.log(0)
    }
    
    window.onscroll = scrollFn()
    
    

    打开控制台我们会看在滚动的同时 scrollFn 函数会执行很多次。在操作DOM和其他交互的时候会非常影响性能,为了避免这个问题,我们一般需要使用一个定时器来对函数进行截流。看下面的截流方法

    function throttle(method, delay){
      let timer = null;
      return function() {
        clearTimeout(timer);
        timer = setTimeout(() => {
          method.apply(this, arguments);
        }, delay);
      }
    }
    
    window.onscroll = throttle(scrollFn(), 250)
    
    

    其实就是利用 setTimeout 的异步队列和闭包,把需要执行的函数缓存起来,然后在指定的事件后执行。

    函数截流: 基本思想是设置一个定时器,在指定时间间隔内运行代码时清除上一次的定时器,并设置另一个定时器,函数请求停止并超过时间间隔才会执行。

    但是这种截流方式在事件不停止的情况下,将永远不会被执行,所以需要对这个截流函数做修改。

    function throttle(method, delay, duration){
      const timer = null;
      let begin = new Date();  
    
      return function() {                
        clearTimeout(timer);
    
        const current = new Date(); 
    
        if(current - begin >= duration){
          method.apply(this, arguments);
          begin = current;
        } else {
          timer = setTimeout(() => {
            method.apply(this, arguments);
          }, delay);
        }
    
      }
    }
    
    window.onscroll = throttle(scrollFn, 100, 500);
    
    

    小程序中在跳转页面的时候多次点击的时候,我们希望它值执行一次,我们看看另一种实现方式不使用 setTimeout 我们不希望它延时执行,我们只是希望在第一次点击后的间隙时间内,只触发一次。

    // utils/index.js
    export const throttle = (fn, gapTime) => {
      if (gapTime == null || gapTime == undefined) {
        gapTime = 1000
      }
    
      let _lastTime = null
    
      // 返回新的函数
      return function () {
        let _nowTime = + new Date()
        if (_nowTime - _lastTime > gapTime || !_lastTime) {
          fn.apply(this, arguments)   //将this和参数传给原函数
          _lastTime = _nowTime
        }
      }
    }
    

    小程序内使用:

    <button
      type='primary'
      bindtap='throttleHandle'
    >
      使用函数截流
    </button>
    
    // click.js
    throttleHandle: throttle(function(e) {
      this.goLogs();
    }, 250),
    

    推荐使用最后一种方法

    相关文章

      网友评论

        本文标题:小程序多次点击最佳实践

        本文链接:https://www.haomeiwen.com/subject/vsgsxqtx.html