在Vuej和query中函数节流和去抖

函数去抖

函数去抖的意思是说当调用该函数n毫秒后,才会执行该函数,若在这n毫秒内又调用此函数则将重新计算执行时间。

function debounce(method,delay,arguments){//method为需要执行的函数,delay是延时时间(毫秒),arguments是method函数需要传递的参数
      var timer=null;
       return function(){
            var context=this, args=arguments;
            clearTimeout(timer);
            timer=setTimeout(function(){
                method.apply(context,args);
            },delay);
        }
}

函数节流

存在一种情况是:假如你不断地调用该函数,利用函数去抖,那么该函数将永远无法执行,因此引入函数节流

函数节流的原理是函数预先设定一个执行周期,当调用动作的时刻大于等于执行周期则执行该动作,则立即执行该函数

var throttle = function(fn, arguments,delay, mustRunDelay){
 	var timer = null;
 	var t_start = new Date();
 	return function(){
 		var context = this, args = arguments, t_curr = new Date();
 		clearTimeout(timer);
 		if(!t_start){
 			t_start = t_curr;
 		}
 		if(t_curr - t_start >= mustRunDelay){
 			fn.apply(context, args);
 			t_start = t_curr;
 		}
 		else {
 			timer = setTimeout(function(){
 				fn.apply(context, args);
 			}, delay);
 		}
 	};
 };

以上是函数节流和函数去抖的基本思路,总体来看是利用闭包的想法,自己的理解是return中返回的是函数,这个函数会用到之前所定义的timer、t_start,所以这些变量没有被立即销毁。

Vue和jquery中使用函数节流去抖

基本的想法是做一个整页滚动的页面

要求是:

  1.在鼠标滚轮往下滚动时候不能让函数响应次数过多,而导致页面快速下翻(函数去抖)

  2.在鼠标滚轮无限滚动时候,依然能够每个一定时间响应函数(函数节流)

鼠标滚轮事件监听

mounted: function () {
    let _this = this
    this.globalValues.begin = new Date()
    $(document).mousewheel(function (event, delta) {
      _this.throttle(_this.mouseRoll, delta, 300, 1300)() //执行throttle函数
    })
  }

一开始我的trottle函数代码如下

function throttle(method,text,delay,duration){
    var timer=null;
    var begin=new Date();    
    return function(){                
        var context=this
        var current=new Date();        
        clearTimeout(timer);
        if(current-begin>=duration){
            method.call(context,text);
            begin=current;
        }else{
            timer=setTimeout(function(){
                method.call(context,text);
            },delay);
        }
    }
}

发现在闭包在这里面并不适用,原因我认为在于 每次重新执行了throttle这个函数,声明了新的变量timer、begin

 _this.throttle(_this.mouseRoll, delta, 300, 1300)() //执行throttle函数

对于这个问题的解决方案,我的想法是在data中定义一个类来装全局的变量,在data中定义的话,这样不会污染整个javascript的全局变量,仅仅是在单个的Vue组件中使用的。

data () {
    return {
      photoPosition: 0,
      globalValues: {
        timer: null,
        begin: null,
        durationNumber: 0,
        number: 0
      }
    }
  },

函数去抖和节流的改进

存在一个情况,就是当我快速滑动鼠标滚轮两下的时候,第一下执行函数认为这个是超过duration,所以这一下会立即执行,接下的一下就会执行setTimeout,当我的delay设置的较小的时候,图片给人的感觉是连续向下翻了两张,这个是我所不希望的。

解决的方案:

data中定义一个durationNumber和number

durationNumber:1或是大于1指函数被理解执行过,0指函数没有被理解执行过

number:用来统计函数被立即执行之后鼠标滚轮滚动的次数,这里我希望是鼠标滚轮再滚两次之后再执行setTimout的函数,这样的delay延时给人的感觉要好很多

throttle: function (method, text, delay, duration) {
      let _this = this
      return function () {
        clearTimeout(_this.globalValues.timer)
        let current = new Date()
        console.log(_this.globalValues.begin)
        if (current - _this.globalValues.begin >= duration) {
          _this.globalValues.begin = current
          _this.globalValues.durationNumber++
          method(text)
        } else {
          if (_this.globalValues.durationNumber) {
            _this.globalValues.number++
            if (_this.globalValues.number <= 2) {

            } else {
              _this.globalValues.timer = setTimeout(function () {
                method(text)
              }, delay)
              _this.globalValues.durationNumber = 0
            }
          }
        }
      }
    }
发布了25 篇原创文章 · 获赞 1 · 访问量 1655

猜你喜欢

转载自blog.csdn.net/weixin_43977647/article/details/89067259