Vue中怎么对事件进行防抖和节流操作?

Vue中怎么对事件进行防抖和节流操作?

有些浏览器事件可以在短时间内快速触发多次,比如调整窗口大小或向下滚动页面。例如,监听页面窗口滚动事件,并且用户持续快速地向下滚动页面,那么滚动事件可能在 3 秒内触发数千次,这可能会导致一些严重的性能问题。

如果在面试中讨论构建应用程序,出现滚动、窗口大小调整或按下键等事件请务必提及 防抖(Debouncing) 和 函数节流(Throttling)来提升页面速度和性能。这两兄弟的本质都是以闭包的形式存在。通过对事件对应的回调函数进行包裹、以自由变量的形式缓存时间信息,最后用 setTimeout 来控制事件的触发频率。

Throttle: 第一个人说了算

throttle 的中心思想在于:在某段时间内,不管你触发了多少次回调,我都只认第一次,并在计时结束时给予响应。

立即学习“前端免费学习笔记(深入)”;

先给大家讲个小故事:现在有一个旅客刚下了飞机,需要用车,于是打电话叫了该机场唯一的一辆机场大巴来接。司机开到机场,心想来都来了,多接几个人一起走吧,这样这趟才跑得值——我等个十分钟看看。于是司机一边打开了计时器,一边招呼后面的客人陆陆续续上车。在这十分钟内,后面下飞机的乘客都只能乘这一辆大巴,十分钟过去后,不管后面还有多少没挤上车的乘客,这班车都必须发走。

在这个故事里,“司机” 就是我们的节流阀,他控制发车的时机;“乘客”就是因为我们频繁操作事件而不断涌入的回调任务,它需要接受“司机”的安排;而“计时器”,就是我们上文提到的以自由变量形式存在的时间信息,它是“司机”决定发车的依据;最后“发车”这个动作,就对应到回调函数的执行。

总结下来,所谓的“节流”,是通过在一段时间内无视后来产生的回调请求来实现的。只要一位客人叫了车,司机就会为他开启计时器,一定的时间内,后面需要乘车的客人都得排队上这一辆车,谁也无法叫到更多的车。

对应到实际的交互上是一样一样的:每当用户触发了一次 scroll 事件,我们就为这个触发操作开启计时器。一段时间内,后续所有的 scroll 事件都会被当作“一辆车的乘客”——它们无法触发新的 scroll 回调。直到“一段时间”到了,第一次触发的 scroll 事件对应的回调才会执行,而“一段时间内”触发的后续的 scroll 回调都会被节流阀无视掉。

现在一起实现一个 throttle:

// 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)

登录后复制

Debounce: 最后一个人说了算

防抖的中心思想在于:我会等你到底。在某段时间内,不管你触发了多少次回调,我都只认最后一次。

继续讲司机开车的故事。这次的司机比较有耐心。第一个乘客上车后,司机开始计时(比如说十分钟)。十分钟之内,如果又上来了一个乘客,司机会把计时器清零,重新开始等另一个十分钟(延迟了等待)。直到有这么一位乘客,从他上车开始,后续十分钟都没有新乘客上车,司机会认为确实没有人需要搭这趟车了,才会把车开走。

我们对比 throttle 来理解 debounce:在throttle的逻辑里,“第一个人说了算”,它只为第一个乘客计时,时间到了就执行回调。而 debounce 认为,“最后一个人说了算”,debounce 会为每一个新乘客设定新的定时器。

现在一起实现一个 debounce:

// 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)

登录后复制

用 Throttle 来优化 Debounce

debounce 的问题在于它“太有耐心了”。试想,如果用户的操作十分频繁——他每次都不等 debounce 设置的 delay 时间结束就进行下一次操作,于是每次 debounce 都为该用户重新生成定时器,回调函数被延迟了不计其数次。频繁的延迟会导致用户迟迟得不到响应,用户同样会产生“这个页面卡死了”的观感。

为了避免弄巧成拙,我们需要借力 throttle 的思想,打造一个“有底线”的 debounce——等你可以,但我有我的原则:delay 时间内,我可以为你重新生成定时器;但只要delay的时间到了,我必须要给用户一个响应。这个 throttle 与 debounce “合体”思路,已经被很多成熟的前端库应用到了它们的加强版 throttle 函数的实现中:

// 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  console.log('触发了滚动事件'), 1000)document.addEventListener('scroll', better_scroll)

登录后复制

在 Vue 里使用 lodash 中的 Debouncing 和 Throttling

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

安装

可以通过 yarn 或 npm 安装 lodash。

# Yarn$ yarn add lodash# NPM$ npm install lodash --save

登录后复制

注意:如果我们不想导入lodash的所有内容,而只导入所需的部分,则可以通过一些Webpack构建自定义来解决问题。 还可以使用lodash.throttle和lodash.debounce等软件包分别安装和导入lodash的各个部分。

throttling 方法

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

  import _ from 'lodash'export default {  methods: {    throttledMethod: _.throttle(() => {      console.log('I get fired every two seconds!')    }, 2000)  }}

登录后复制

debouncing 方法

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

  import _ from 'lodash'export default {  methods: {    throttledMethod: _.debounce(() => {      console.log('I only get fired once every two seconds, max!')    }, 2000)  }}

登录后复制

参考:

Throttling and Debouncing in JavaScript

The Difference Between Throttling and Debouncing

Examples of Throttling and Debouncing

Remy Sharp’s blog post on Throttling function calls

前端性能优化原理与实践

相关推荐:

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

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

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

以上就是Vue中怎么对事件进行防抖和节流操作?的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/3023163.html

(0)
上一篇 2025年3月13日 06:04:08
下一篇 2025年3月4日 22:05:30

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • 深入了解vue.js中的diff算法

    本篇文章给大家详细了解一下vue.js中的diff算法。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。 前言 我的目标是写一个非常详细的关于diff的干货,所以本文有点长。也会用到大量的图片以及代码举例,目的让看这篇文章的…

    2025年3月13日 编程技术
    200
  • 浅谈vue.js中的Props(单向数据流)

    prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。这是为了防止子组件无意修改了父组件的状态——这会让应用的数据流难以理解。 另外,每次父组件更新时,子组件的所有 prop 都会更新为最新值。这意味着你不应该在子组…

    2025年3月13日
    200
  • 详解vue.js中watch的使用

    在vue中,使用watch来响应数据的变化。watch的用法大致有三种。下面代码是watch的一种简单的用法: 登录后复制登录后复制 new Vue({  el: ‘#root’,  data: {    cityName: ‘shangh…

    2025年3月13日
    200
  • 深入浅析With的使用

    with用于扩展一个语句的作用域链,但一般情况下不建议使用with语句,因为它可能是引起混淆错误和兼容性问题的根源。在Vue源码中有使用with语句的功能点,因此在这里将简介其功能,以助于阅读框架源码。 性能的利与弊 利 with语句可以在…

    2025年3月13日
    200
  • 浅谈Vue.use到底是什么?

    Vue.use到底是什么鬼、下面本篇文章就来给大家介绍一下Vue.use。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。 我们在使用Vue做项目开发的时候,看到不少轮子都是通过Vue.use来进行使用,感觉甚是高大上。 不…

    2025年3月13日
    200
  • 浅谈Vue.js中双向绑定的原理及实现方法

    Vue最独特的特性之一,是其非侵入性的响应式系统。数据模型仅仅是普通的JavaScript对象。而当你修改它们时,视图会进行更新。vue通过双向绑定实现,本文就来为大家介绍一下vue双向绑定原理及实现方法。 本文主要介绍两大内容: 1. v…

    2025年3月13日 编程技术
    200
  • 详解vue.js中如何处理事件

    下面vue.js教程给大家介绍一下使用vue.js处理事件的方法,希望对大家有一定的帮助。 当您使用Vue构建动态网站时,您很可能希望它能够响应事件。 例如,如果用户单击按钮,提交表单,甚至只是移动鼠标,您可能希望您的Vue网站以某种方式做…

    2025年3月13日
    200
  • 实现带有进度条的Vue延迟加载

    下面vue.js栏目给大家介绍一下给vue的惰性加载添加进度条的方法。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。 简介 通常用 Vue.js 编写单页应用(SPA)时,当加载页面时,所有必需的资源(如 JavaScri…

    2025年3月13日
    200
  • 浅谈vue-cli初始化Vue项目的项目结构

    概述 vue-cli是vue 提供的一个官方命令行工具,可用于快速搭建大型单页应用。该工具提供开箱即用的构建工具配置,带来现代化的前端开发流程。只需几分钟即可创建并启动一个带热重载、保存时静态检查以及可用于生产环境的构建配置的项目。 使用v…

    2025年3月13日 编程技术
    200
  • 分析一下Vue.use的源码

    有过vue开发经验的,对于vue.use并不陌生。当使用vue-resource或vue-router等全局组件时,必须通过Vue.use方法引入,才起作用。那么vue.use在组件引入之前到底做了那些事情呢? 先上vue.use源码 Vu…

    2025年3月13日
    200

发表回复

登录后才能评论