Home > Web Front-end > Vue.js > body text

How to anti-shake and throttle events in Vue?

青灯夜游
Release: 2020-10-13 13:34:01
forward
2347 people have browsed it

How to anti-shake and throttle events in Vue?

Some browser events can be triggered multiple times quickly in a short period of time, such as resizing a window or scrolling down a page. For example, if you listen to page window scroll events, and the user continues to scroll down the page quickly, the scroll event may fire thousands of times in 3 seconds, which may cause some serious performance issues.

If you discuss building an application during an interview and events such as scrolling, window resizing, or key presses occur, be sure to mention debouncing and function throttling to improve page speed and performance. The essence of these two brothers exists in the form of closure. By wrapping the callback function corresponding to the event, caching the time information in the form of a free variable, and finally using setTimeout to control the triggering frequency of the event.

Throttle: The first person has the final say

The central idea of ​​throttle is: within a certain period of time, no matter how many triggers you have For each callback, I only recognize the first time and respond when the timer expires.

Let me tell you a little story first: A passenger just got off the plane and needed a car, so he called the only airport bus at the airport to pick him up. The driver drove to the airport, thinking that he had already come, so he should pick up a few more people to go with him, so that the trip would be worthwhile - I'll wait ten minutes and see. So the driver turned on the timer and greeted the guests behind him to get on the bus one after another. During these ten minutes, the passengers who got off the plane at the back can only take this bus. After ten minutes, no matter how many passengers behind the plane are not crowded on the bus, this bus must be sent away.

In this story, the "driver" is our throttle, which controls the timing of departure; the "passenger" is the callback tasks that continue to pour in due to our frequent operating events, and it needs to accept the "driver" The arrangement; and the "timer" is the time information in the form of a free variable mentioned above, which is the basis for the "driver" to decide to start the train; finally, the action of "departure" corresponds to the execution of the callback function.

To sum up, the so-called "throttling" is achieved by ignoring subsequent callback requests for a period of time. As long as a guest calls for a ride, the driver will start a timer for him. Within a certain period of time, all subsequent guests who need a ride will have to queue up to get on this ride, and no one can call for more rides.

It corresponds to the actual interaction: whenever the user triggers a scroll event, we start the timer for this trigger operation. For a period of time, all subsequent scroll events will be treated as "passengers in a car" - they cannot trigger new scroll callbacks. Until "a period of time" is reached, the callback corresponding to the scroll event triggered for the first time will be executed, and subsequent scroll callbacks triggered "within a period of time" will be ignored by the throttle valve.

Now realize a throttle together:

// fn是我们需要包装的事件回调, interval是时间间隔的阈值
function throttle(fn, interval) {
  // last为上一次触发回调的时间
  let last = 0
  
  // 将throttle处理结果当作函数返回
  return function () {
      // 保留调用时的this上下文
      let context = this
      // 保留调用时传入的参数
      let args = arguments
      // 记录本次触发回调的时间
      let now = +new Date()
      
      // 判断上次触发的时间和本次触发的时间差是否小于时间间隔的阈值
      if (now - last >= interval) {
      // 如果时间间隔大于我们设定的时间间隔阈值,则执行回调
          last = now;
          fn.apply(context, args);
      }
    }
}

// 用throttle来包装scroll的回调
const better_scroll = throttle(() => console.log('触发了滚动事件'), 1000)
Copy after login

Debounce: The last person has the final say

The central idea of ​​anti-shake Yu: I will wait for you to the end. Within a certain period of time, no matter how many callbacks you trigger, I will only recognize the last one.

Continue to tell the story of the driver driving. This time the driver was more patient. After the first passenger gets on the bus, the driver starts timing (say ten minutes). Within ten minutes, if another passenger comes up, the driver will clear the timer and start waiting for another ten minutes (delayed waiting). Until there is such a passenger, and no new passengers get on the bus for the next ten minutes since he got on the bus, the driver will think that no one really needs to take this bus, and will drive away.

Let’s compare throttle to understand debounce: In the logic of throttle, “the first person has the final say”, it only times the first passenger, and executes the callback when the time is up. Debounce believes that "the last person has the final say" and debounce will set a new timer for each new passenger.

Now implement a debounce together:

// fn是我们需要包装的事件回调, delay是每次推迟执行的等待时间
function debounce(fn, delay) {
  // 定时器
  let timer = null
  
  // 将debounce处理结果当作函数返回
  return function () {
    // 保留调用时的this上下文
    let context = this
    // 保留调用时传入的参数
    let args = arguments

    // 每次事件被触发时,都去清除之前的旧定时器
    if(timer) {
        clearTimeout(timer)
    }
    // 设立新定时器
    timer = setTimeout(function () {
      fn.apply(context, args)
    }, delay)
  }
}

// 用debounce来包装scroll的回调
const better_scroll = debounce(() => console.log('触发了滚动事件'), 1000)
Copy after login

Use Throttle to optimize Debounce

The problem with debounce is that it is "too complex" Be patient." Just imagine, if the user operates very frequently - he does not wait for the delay time set by debounce to end before performing the next operation, so every time debounce regenerates the timer for the user, the callback function is delayed countless times. . Frequent delays will cause users to get no response, and users will also have the impression that "this page is stuck."

In order to avoid self-defeating, we need to borrow the idea of ​​throttle to create a "bottom line" debounce - you can wait, but I have my principles: within the delay time, I can regenerate the timing for you server; but as soon as the delay time is up, I must give the user a response. This "combination" idea of ​​throttle and debounce has been applied by many mature front-end libraries to the implementation of their enhanced throttle function:

// fn是我们需要包装的事件回调, delay是时间间隔的阈值
function throttle(fn, delay) {
  // last为上一次触发回调的时间, timer是定时器
  let last = 0, timer = null
  // 将throttle处理结果当作函数返回
  
  return function () { 
    // 保留调用时的this上下文
    let context = this
    // 保留调用时传入的参数
    let args = arguments
    // 记录本次触发回调的时间
    let now = +new Date()
    
    // 判断上次触发的时间和本次触发的时间差是否小于时间间隔的阈值
    if (now - last < delay) {
    // 如果时间间隔小于我们设定的时间间隔阈值,则为本次触发操作设立一个新的定时器
       clearTimeout(timer)
       timer = setTimeout(function () {
          last = now
          fn.apply(context, args)
        }, delay)
    } else {
        // 如果时间间隔超出了我们设定的时间间隔阈值,那就不等了,无论如何要反馈给用户一次响应
        last = now
        fn.apply(context, args)
    }
  }
}

// 用新的throttle包装scroll的回调
const better_scroll = throttle(() => console.log('触发了滚动事件'), 1000)

document.addEventListener('scroll', better_scroll)
Copy after login

Use debouncing and debounce in lodash in Vue Throttling

事件节流和防抖是提高性能或降低网络开销的好方法。虽然 Vue 1曾经支持对事件的节流和防抖,但是在Vue 2中为了保持核心的简单性,删除对事件的节流和防抖的支持。因此,在Vue 2对对事件进行防抖和节流我们可以使用 lodash 来做。

安装

可以通过 yarn 或 npm 安装 lodash。

# Yarn
$ yarn add lodash
# NPM
$ npm install lodash --save
Copy after login
注意:如果我们不想导入lodash的所有内容,而只导入所需的部分,则可以通过一些Webpack构建自定义来解决问题。 还可以使用lodash.throttlelodash.debounce等软件包分别安装和导入lodash的各个部分。

throttling 方法

要对事件进行节流处理方法非常简单,只需将要调用的函数包装在lodash的_.throttle函数中即可。



Copy after login

debouncing 方法

尽管节流在某些情况下很有用,但一般情况我们经常使用的是防抖。 防抖实质上将我们的事件分组在一起,并防止它们被频繁触发。 要在Vue组件中使用节流,只需将要调用的函数包装在lodash的_.debounce函数中。



Copy after login

参考:

相关推荐:

2020年前端vue面试题大汇总(附答案)

vue教程推荐:2020最新的5个vue.js视频教程精选

更多编程相关知识,请访问:编程入门!!

The above is the detailed content of How to anti-shake and throttle events in Vue?. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:segmentfault.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact [email protected]
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!