Vue节流的原理及应用

发布时间:2023-05-19

Vue节流方法

Vue的节流方法是指在某个时间间隔内只执行一次函数。这个方法适用于那些需要频繁触发的 DOM 事件函数,如scroll,mousemove等。节流的原理是设置一个定时器,在定时器内执行函数,每次函数执行完毕后清除定时器,再次触发时重新设置定时器。

Vue节流封装

Vue的节流可用以下封装代码,这样就可以直接在 Vue 实例中调用:

Vue.prototype.$throttle = function(fn, delay) {
 let lastTime = 0;
 return function() {
   let nowTime = new Date().getTime();
   if (nowTime - lastTime > delay) {
     fn.apply(this, arguments);
     lastTime = nowTime;
   }
 };
};

使用时可以这样:

// 定义事件函数
function handleScroll() {
 console.log("scrolling");
}
// 传入事件函数和时间间隔
window.addEventListener("scroll", this.$throttle(handleScroll, 1000));

Vue节流防抖

Vue的节流防抖是指在函数触发后,在规定时间之内再次触发将被忽略。这个方法适用于那些频繁触发的函数事件,如输入框的输入事件,对于一些用户需要输入,但是输入过快会导致频繁的数据更新请求,可以使用节流防抖以减少请求次数。 防抖的原理是使用 setTimeout 函数,每次触发时清除一个定时器,如果在指定时间间隔内再次触发则重新设置定时器。

Vue.prototype.$debounce = function(fn, delay) {
 let timer = null;
 return function() {
   clearTimeout(timer);
   timer = setTimeout(() => {
     fn.apply(this, arguments);
   }, delay);
 };
};

使用时可以这样:

// 定义事件函数
function handleInput() {
 console.log("inputting");
}
// 传入事件函数和时间间隔
this.$refs.input.addEventListener("input", this.$debounce(handleInput, 500));

Vue节流阀

Vue的节流阀是一个很实用的功能,主要用于控制短时间内多次请求。它可以控制一段时间内最多可以请求几次,达到限制后会自动暂停。这个功能适用于那些用户触发频率高,但是并不需要每个都更新后端数据的情况,适用于推荐列表,热门搜索等。

Vue.prototype.$createThrottleValve = function(limitCount, limitTime) {
 const records = [];
 let timer = null;
 return function(fn) {
   const now = Date.now();
   records.push(now);
   if (records.length > limitCount) {
     const removeCount = records.findIndex(
       (time) => now - time < limitTime
     );
     records.splice(0, removeCount);
   }
   if (records.length >= limitCount) {
     clearTimeout(timer);
     const firstTime = records[0];
     const diffTime = limitTime - (now - firstTime);
     timer = setTimeout(() => {
       fn();
     }, diffTime);
     return;
   }
   fn();
 };
}

使用时可以这样:

// 定义事件函数
function handleHotSearch() {
 console.log("request hot search");
}
// 传入事件函数和请求限制
const throttleValve = this.$createThrottleValve(5, 1000);
this.$refs.hotSearch.addEventListener("click", function() {
 throttleValve(handleHotSearch);
});

Vue节流只执行最后一次接口

Vue的节流还可以只执行最后一次接口。这个方法适用于在一些需要连续触发请求的场景下,只需要保留最后一次的数据更新即可。还是使用 setTimeout 函数来实现的,但是需要注意到如果设置间隔时间太短则不会执行两次,需要根据实际场景调整时间。

Vue.prototype.$onlyLastReq = function(fn, delay) {
 let timer = null;
 return function() {
   clearTimeout(timer);
   timer = setTimeout(() => {
     fn.apply(this, arguments);
   }, delay);
 };
};

使用时可以这样:

// 定义事件函数
function handleUpdate() {
 console.log("request update");
}
// 传入事件函数和时间间隔
window.addEventListener("scroll", this.$onlyLastReq(handleUpdate, 500));

Vue节流指令

对于一些频繁触发的 DOM 事件,还可以使用 Vue 的自定义指令来实现节流。在注册指令时可以通过参数传入时间间隔,对于同一 DOM 元素,限制时间间隔内只能被触发一次。

Vue.directive('throttle-click',{
 inserted:function(el,binding){
   let delay = binding.arg || 600
   let timer
   el.addEventListener('click', () => {
     if(!timer){
       timer = setTimeout(() => {
         timer = null
         binding.value()
       }, delay)
     }
   })
 }
})

使用时可以这样:

<button v-throttle-click="handleClick" :arg="500">Click Me</button>

Vue节流防抖插件

Vue还有很多优秀的开源插件可供使用,其中就有很多封装了 Vue 的节流或防抖功能。 如 lodash 的 debounce 函数:

import _ from 'lodash'
export default {
 methods:{
   handleClick: _.debounce(function(){
     console.log('click')
   }, 1000)
 }
}

使用时可以这样:

<button @click="handleClick">Click Me</button>

Vue节流按钮

Vue 的节流按钮是一个非常实用的功能,可以在限制时间内防止按钮重复点击。可以使用组件封装的方式来实现节流按钮。

<template>
 <button :disabled="isThrottling" @click="runHandler">
   {{ buttonText }}
 </button>
</template>
<script>
export default {
 props: {
   handler: { type: Function, required: true },
   delay: { type: Number, default: 300 },
   text: { type: String, default: "Click" },
 },
 data() {
   return {
     isThrottling: false,
   };
 },
 computed: {
   buttonText() {
     return this.isThrottling ? `${this.text}ing...` : this.text;
   },
 },
 methods: {
   runHandler() {
     if (!this.isThrottling) {
       this.isThrottling = true;
       this.handler();
       setTimeout(() => {
         this.isThrottling = false;
       }, this.delay);
     }
   },
 },
};
</script>

使用时可以这样:

<throttlebutton :handler="handleClick" :delay="1000" text="Click Me" />

Vue节流函数失效选取

在使用 Vue 的节流或防抖方法时,需要根据不同实际情况和业务需求选择不同的节流方法,避免出现无效操作和效果不佳的情况。 节流方法的间隔时间不能过长或过短,过长会影响用户的体验,过短会导致触发事件太频繁,失去节流效果。 防抖方法的间隔时间也不能过长或过短,过长会导致用户输入有延迟的感觉,过短则会导致多次请求,降低性能。 同时,需要根据实际业务需求选择节流阀或只保留最后一次接口等方法,避免频繁请求和更新。

总结

Vue提供了多种节流防抖方法和插件,可以用来优化用户体验和提高性能。需要根据实际业务需求选择不同的节流方法,避免出现无效操作和效果不佳的情况。