事件节流 & 节流事件

在浏览器 DOM 事件里面,有一些事件会随着用户的操作不间断触发。比如:resize、scroll、mousemove。这并不是我们想要的,因为有的时候如果事件处理方法比较庞大,DOM 操作比如复杂,还不断的触发此类事件就会造成性能上的损失,导致用户体验下降(UI 反映慢、浏览器卡死等)。所以,这个时候,事件节流就显得相当重要了。

在这里我将列举几条节流方案

1.javascript 提供了throttle()函数,它的实现如下

    var throttle = function (fn, delay, atleast) {
        var timer = null;
        var previous = null;

        return function () {
            var now = +new Date();

            if ( !previous ) previous = now;
            if ( atleast && now - previous > atleast ) {
                fn();
                // 重置上一次开始时间为本次结束时间
                previous = now;
                clearTimeout(timer);
            } else {
                clearTimeout(timer);
                timer = setTimeout(function() {
                    fn();
                    previous = null;
                }, delay);
            }
        }
    };  

  点击查看原文

我没有考证这个函数的具体实现,暂且已上文做为一种节流方法

2.第二种节流方案

(function($) {
    var timer = 0;
    $(window).scroll(function() {
      if (!timer) {
        timer = setTimeout(function() {
         //一些操作;
          timer = 0;
        }, 250);
      }
    }).trigger('scroll');
  });
})(jQuery);

  这里虽然用到了JQuery  的符号,但是没有什么关系。我想说的是,这种节流方案,是我比较赞同的。第一条节流方案,虽然也达到了相同的结果,但是在不断    创建和删除   定时器。这并不见得对性能有多友好。相比较,第二种方案,通过设置一个开关,在第一次滚动时通过判断进入if语句,这时改变了timer变量的值,使接下来的scroll事件,都不能进入if,执行事件的操作。定时器事件执行之后,timer变量又被赋值为0。这样又能进入if判断语句。这个开关机制相比较,简单,更实用

 

3.第三种节流方案

(function($) {
    var scrolled = false;
    $(window).scroll(function() {
      scrolled = true;
    });
    setInterval(function() {
      if (scrolled) {
        //一些操作
        scrolled = false;
      }
    }, 250);
  
  
})(jQuery);

  这种节流方案也是一种奇思妙想,将事件的处理函数放在一个setInterval()函数中,每间隔一段事件监测一次是否发生了scroll事件,然后执行,而scroll事件只执行一个开关的作用,这个想法很好。

 

4.在前面的基础上,我们再加点JQuery事件,问题会更简单。

我们想创建一个特殊事件,这样以后我们的项目中,直接可以绑定这个事件,就不用再判断什么条件了

(function() {
	$.event.special.throttledScroll = {
		setup: function(data) {
			var timer = 0;
			$(this).on('scroll.throttledScroll', function() {
				if(!timer) {
					timer = setTimeout(function() {
						$(this).triggerHandler('throttledScroll');
						timer = 0;
					}, 200)
				}
			})
		},
		teardown: function() {
			$(this).off('scroll.throttledScroll');
		}
	}
})(jQuery);

$(document).ready(function() {
	var i = 0
	$(window).on('throttledScroll', function() {
		console.log(i);
		i++;
	})
});

  这里我创建了一个jQuery事件,在这个事件内部做了之前的判断,所以后面,我只用绑定我定义的这个特殊事件就可以监控scroll事件了,并且还是经过节流处理的。

 

谢谢关注

 

posted @ 2017-07-05 13:49  Your-lord  阅读(1585)  评论(0编辑  收藏  举报