Vue 防抖与节流の使用

18,137 阅读2分钟

文章已同步至【个人博客】,欢迎访问【我的主页】😃
文章地址:blog.fanjunyang.zone/archives/js…

场景

在一个电影项目中,我想在电影的列表中,保存下拉的当前位置,防止你切换页面后,再切换回当前的电影列表页,他就又回到电影的第一条数据。
这时候,我不想每次只要滑动一点,就保存当前位置,我想隔一段时间,保存一次,这时候,就可以使用防抖和节流。

概念

说白了,防抖节流就是使用定时器来实现我们的目的。

关于定时器的用法,请移步:JS中常用计时器的用法

防抖(debounce):

在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。

典型的案例就是输入框搜索:输入结束后n秒才进行搜索请求,n秒内又输入的内容,则重新计时。

节流(throttle):

规定在一个单位时间内,只能触发一次函数,如果这个单位时间内触发多次函数,只有一次生效。

典型的案例就是鼠标不断点击触发,规定在n秒内多次点击只生效一次。

用法

防抖(debounce)

下拉列表,隔一段时间保存当前下拉位置。

我们可以在mounted钩子中实现我们的防抖:

// 防抖  定时器
let timer;

//list就是电影列表	ref="list"	$el获取DOM元素
this.$refs.list.$el.addEventListener("scroll", e => {
	console.log("---->",e.target.scrollTop)	//不使用防抖
	if (timer) {
		//清空timer
		clearTimeout(timer);
	}
	timer = setTimeout(() => {
		console.log(e.target.scrollTop)	//使用防抖
		
		//在sessionStorage中保存当前下拉位置
		// sessionStorage.setItem("position", e.target.scrollTop);
	}, 75);		//75ms为最佳
});

效果演示(隔一段时间保存当前位置):
---->为不使用防抖,没加的则使用防抖

输入框搜索隔段时间进行搜索请求:

<template>
  <div>
    <input type="text" @keyup="debounce" />
  </div>
</template>

<script>
//定义 timer
let timer;
export default {
  methods: {
    debounce: function() {
      if (timer) {
        clearTimeout(timer);
      }
      timer = setTimeout(() => {
        console.log("防抖...");
        timer = undefined;
      }, 2000);
    }
  }
};
</script>

节流(throttle)

在n秒内点击多次,只有一次生效。


<template>
  <div>
    <button @click="throttle">按钮</button>
  </div>
</template>

<script>
//定义
let timer, lastTime;
let now = +new Date();
export default {
  methods: {
    throttle: () => {
      if (lastTime && now - lastTime < 200) {
        clearTimeout(timer);
        console.log("....");
        timer = setTimeout(() => {
          console.log("点击...");
          lastTime = +new Date();
        }, 2000);
      } else {
        lastTime = now;
        timer = setTimeout(() => {
          console.log("点击...");
          lastTime = +new Date();
        }, 200);
      }
    }
  }
};
</script>

效果演示:

补充

当然,也可以对这两个方法进行封装,以便在多处使用。

// 防抖(在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时)
function debounce(fn, delay) {
    let t = delay || 500
    let timer
    return function() {
        clearTimeout(timer)
        timer = setTimeout(() => {
            // 改变this指向并传递参数
            fn.apply(this, arguments)
        }, t)
    }
}

// 节流(规定在一个单位时间内,只能触发一次函数,如果这个单位时间内触发多次函数,只有一次生效)
function throttle(fn, delay) {
    let t = delay || 500
    let timer
    return function() {
        if (!timer) {
            timer = setTimeout(() => {
                // 为了方便下次执行定时器
                timer = null
                fn.apply(this, arguments)
            }, t)
        }
    }
}

V_V