戳蓝字「前端技术优选」关注我们哦!

作者:yeyan1996

https://juejin.im/post/6892577964458770445

应某人的要求被迫营业,望各位看官不要吝啬手中的赞-。-

背景

在使用 uni-app 开发小程序时,有个填写表单的需求,包含两个输入框,看起来像这样

image-20201107143814796

两个在普通不过的输入框

因为需要复用一些样式和逻辑,所以将输入框抽象成了组件,代码简化后如下



子组件代码



由于在父组件中需要依赖输入的值请求接口,为避免接口频繁调用,这边引入 lodash debounce 用于防抖

这个需求在 yeyan1996 眼中没有任何难度,但在几天后却收到了部分用户反馈,说在两个输入框分别填写了值,但最终只有一个输入框有效

这时才回头想起代码中的 debounce ....

问题原因

收到用户反馈后,yeyan1996 尝试多次点击输入框,发现问题并不是必现,最终总结出了规律

填写第一个输入框后,快速对第二个输入框进行输入,才会造成最终的表单数据中只有一个值的问题

通过下图子组件的 log 可以看到,虽然 ui 界面显示两个输入框都有值,但实际只触发了第二个输入框的 log

Kapture 2020-11-07 at 14.58.57

之所以 ui 界面显示两个输入框都有值,是因为是用户直接和 textarea 控件交互,实际并没有更新控件绑定的 value 值

最终结论:第一个输入框中被 debounce 包裹的函数并没有执行

是防抖问题么?

尝试将 debounce 去掉后,果然 bug 解决了

Kapture 2020-11-07 at 15.06.41

那么,是防抖的问题么?

不妨先思考下 Vue 组件的实现原理,我在 [Vue.js进阶]从源码角度剖析Vue的生命周期 中提到过,每个 .vue 文件可以理解为一个构造函数,或者一个 Class,而在父组件中引用组件就等于对其的实例化

  

上述代码即创建了 2 个 CustomTextarea 组件的实例

熟悉面向对象的同学应该知道,构造函数实例化时,同时会创建实例的属性和方法,一般每个实例的属性都不相同,而方法因为是函数,所以会复用,已达到节省内存的效果

class Person {  constructor(name) {    this.name = name  }  eat() {}}

const person1 = new Person('张三')const person2 = new Person('李四')

console.log(person1.name === person2.name) // falseconsole.log(person1.eat === person2.eat) // true

Vue2  的组件借鉴了面向对象的原理,虽然内部的实现方式不同,但最终的行为一致,即组件的每个实例都拥有不同的 data,但会复用相同的 methods

源码地址:https://github.com/vuejs/vue/blob/dev/src/core/instance/state.js#L286

image-20201107155528333

286 行中 methods 对象是每个组件实例共用的,每实例化一个组件,会创建相同的引用,指向 methods 中的函数

未命名

上图案例中, 所有 custom-textarea 中的 handleInput 都指向同一个函数,而作为 props 的 value 字段是通过父组件传入的,并不会共享(分别为 text1/text2)

解决方案

经过上述的分析,答案显而易见,两个组件实例都指向了同一个被 debounce 包裹的 handleInput 函数

所以在输入第一个值后, 1000 毫秒内快速切换到第二个输入框进行输入,此时由于防抖效果仍存在,导致第一次的输入并没有计算在内

而第二次输入完毕后,经过 1000 毫秒,最终只会执行第二个 custom-textarea 的 handleInput

只要使得每个组件实例的 handleInput 互相独立,即可解决问题



将 handleInput 从 methods 放到 data 中,每次初始化时创建防抖函数,此时每个组件实例的 handleInput 就不会互相干扰

Kapture 2020-11-07 at 16.44.41

大功告成???

题外话

Vue 组件中通过将 data 定义为一个函数,函数的返回值作为组件的数据来源,使得每个组件实例的数据都不相同

而 Vue 组件中 methods 是所有实例共用的,那么对于 watch/computed/生命周期,它们是否会共用的呢?



和 methods 对象相同,computed 对象的属性名是一个响应式变量,而值是一个函数,所以所有实例也会指向同一个函数,但由于这个函数需要有返回值,所以不会用防抖函数进行包裹,很少遇到函数公用导致的问题

而 watch 也和 methods 对象相同,所有组件实例共用,所以也会存在防抖的问题

至于生命周期本身就是一个函数,如果对生命周期设置了防抖,多个组件实例同时初始化时也会造成只执行一次的情况

参考资料

[Vue.js进阶]从源码角度剖析Vue的生命周期

【Vue原理】Methods - 源码版](https://segmentfault.com/a/1190000019605909)

在看点这里

使用lodash防抖_什么,lodash 的防抖失效了?相关推荐

  1. 防抖和节流——lodash插件

    首先了解一下什么是防抖.节流 防抖:当前的所有的触发都被取消,最后一次在规定时间内才会触发,即如果连续快速触发,只会执行一次. 节流:把频繁的触发变为少量的触发,可以给浏览器充裕的时间解析代码 防抖就 ...

  2. vue防抖和节流是什么_前端节流和防抖的区别

    在监听某类事件时,如监听元素滚动或表单input事件时,处理函数在短时间内被频繁调用. 如果处理函数还需要调用后台接口,那么可能上次还没有响应,下一次请求又来了.这样无意中增加了服务器的压力,而且对用 ...

  3. java接口防抖_彻底弄懂节流和防抖

    节流和防抖 这两个东西,你肯定听过,就是两种优化浏览器性能的手段.相关文章你肯定也看过,如果还是不太清楚,没关系,看完这篇短文,相信你能轻松理解其中差别. 防抖(deounce) 我们先说防抖吧,这里 ...

  4. 开源阅读书源_阅读_一个永远不会失效的小说阅读软件

    对于一个爱看小说的人阅读这款APP应该不陌生,不是那些手机里自带的"阅读"哦! 软件界面: 从界面来看是十分精美的,布局完全按照用户需求布置,操作十分简单.现在的小说阅读软件要不就 ...

  5. java接口防抖_前端性能优化:高频执行事件/方法的防抖

    日期:2013-6-25  来源:GBin1.com 高频执行事件/方法的防抖 通常,开发人员会在有用户交互参与的地方添加事件,而往往这种事件会被频繁触发.想象一下窗口的resize事件或者是一个元素 ...

  6. 按键防抖_单片机用一个IO口采集多个按键信号

    一般按键信号都是高低电平,对于每一个按键信号单片机都需要一个IO口进行采集,这种按键采集方式比较简单,但是占用的单片机IO口比较多. 如果按键非常多,例如键盘,可以采用行列阵列方式进行信号采集.这种方 ...

  7. 二自由度云台扫描算法_几款超级防抖手持云台,拍摄大片绝不抖

    而今是Vlog的盛世时代,每一个年轻人都有一个vlog梦想,手机也可以拍出大片,总是苦于拍摄出的东西效果不好?不敢跟拍?一边跑一边手机摄影就糊成一团?那么怎么告别萌呆定点拍摄,今天给大家分享几款可以拍 ...

  8. java接口防抖_防抖函数丶Java教程网-IT开发者们的技术天堂

    1.使用场景:是在写keyup事件的时候,每次触发,都会请求后台接口,为了避免,每次请求,键盘弹起之后,隔上一段时间再去请求,所以用防抖函数 2.概念: (1)什么是防抖:多次事件触发后.事件处理函数 ...

  9. java接口防抖_花式解说防抖函数debounce的实现

    歪式絮叨:原本打算只用一篇文章总结下防抖和节流的,但是写着写着发现挺有意思的.所以准备会分成 3-4 篇来写了,单独的防抖和节流的实现,然后在去分享一下知名库的源码.今天先跟歪马一起看看防抖的实现吧. ...

最新文章

  1. TS和JS相对比的优势
  2. WRF-Chem User Guide3.9.1.1 部分内容翻译
  3. 从零学前端第十四讲:AngularJs进阶-作用域和控制器
  4. python 插补数据_python 2020中缺少数据插补技术的快速指南
  5. ASP.NET Application,Session,Cookie和ViewState等对象用法和区别
  6. 在idea中配置jetty
  7. Unix/Linux环境C编程新手教程(40) 初识文件操作
  8. android谷歌打印插件下载地址,谷歌浏览器打印插件(Print Plus)
  9. Android 状态栏背景颜色修改与状态栏字体颜色修改
  10. 将多名学生成绩绘制在一张画布中,并在图中显示学生成绩
  11. 东芝和摩飞多功能锅到底哪一款值得拔草呢?本篇深度评测让你剁手不后悔;
  12. 湖南大学计算机考研科目2020,2020湖南大学计算机与软件工程考研初试科目、参考书目、录取情况全解析...
  13. Uboot启动分析--start.S启动分析(1)
  14. RGB(三色)灯配置常用颜色数据,用法讲解,基于C语言的程序讲解,七彩渐变程序讲解
  15. 多个域名泛域名证书和多域名证书
  16. 免费版医疗器械计算机软件,医疗器械软件描述.docx
  17. Linux 调试之 TRACE_EVENT(三)
  18. 百度小程序版帝国cms插件
  19. LSM303AGR开发中遇到的问题
  20. 为 repo ‘AppStream‘ 下载元数据失败 错误:为 repo ‘AppStream‘ 下载元数据失败

热门文章

  1. catia曲面扫掠命令详解_Mastercam快捷键命令,附中英文功能讲解!值得收藏!
  2. linux ftp 工作过程,linux中ftp的安装过程记录[运维篇]
  3. python 的钻石继承问题
  4. Java GUI 基础知识
  5. 找准切入点,调试看源码,事半功倍
  6. 学习 sentry 源码整体架构,打造属于自己的前端异常监控SDK
  7. 02如何抓住重点,系统高效地学习数据结构与算法?
  8. apache配置文件详解与优化
  9. Android GridView LruCache
  10. KDD走进阿里 数百专家聚集探讨产学研一体化