LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

input事件重复触发?可能是输入法搞的鬼

freeflydom
2025年11月6日 10:13 本文热度 155

问题的起因

有这样一个需求,需要用户在输入手机号的时候,进行3-4-4这样格式化展示。

<!-- 用户输入 -->
13000000000
<!-- 前端展示 -->
130 0000 0000

这个是一个比较常见的需求,在很多应用我们都见过,其处理的原理,就是用户在input输入框的输入过程中,监听input事件,对input的内容进行格式化。

既然知道该怎么处理了,那就简单了,直接进入浩瀚的网络,找一下这个替换的正则,是怎么写的,毕竟借鉴前人的肩膀,才能看的更高。经过一番搜索,找到了如下代码:

handleInput = (curVal) => {
  const curValLen = curVal?.length || 0
  const oldValLen = this.oldVal?.length || 0
  // 如果新输入的值的数量,大于旧值得话,就是用户在新增,就需要格式化,那么就需要在输入的过程中,添加空格。
  // 反之,那么就是用户,在删除,我们做的操作,就只需要,删除末尾的空格而已
  return curValLen > oldValLen
    ? curVal
      .replace(/\s/g, '')
      .replace(/(\d{3})(\d{0,4})(\d{0,4})/, '$1 $2 $3')
    : curVal.trim()
}

经过测试,功能非常漂亮,没有任何问题,是时候准备收工下班了。

问题的发现

由于这个功能是涉及登录注册的,使用的非常频繁,当我把这个功能发布到测试环境的时候,风平浪静,没有任何人提出问题,我自认为,这个功能稳了,哪知道,我偶尔登录注册,输入手机号的时候,会出现这样的情况。

// 我的输入:123
// 页面展示:123 3
// 总是在用户输入第三个字符的时候,出现重复。

最初,我以为是我自己,输入过快了,导致重复,后面经过我,小心翼翼的测试,发现确实有这个的问题,输入了一次,但是input重复触发了两次。

而且这个bug产生的情况,特别诡异,如果触发了,就会一直触发,不触发,就一直不会触发,你说他是偶现,他确实是偶现,你说他是必现,当这个bug如果偶现了,那么后续这一段时间,就会一直出现,那就是偶现中的必现。

此时,我内心有点不知所措,我觉得应该请教大众的网友了,上网搜索了一番,看看大家会不会出现同样的问题,我出现了这个问题,那么其他人也可能出现,而且还是这么常见的问题。

问题的探索

经过我的搜索,可能有以下原因:

  1. input事件和change事件同时绑定导致
  2. 子组件/父组件同时绑定的input事件
  3. v-model绑定的值,格式化的时候,导致input又触发
  4. 中文输入法,导致input重复触发

按照这几个方向,排查了一遍,我开始怀疑是因为,正则的问题, 是不是因为133的时候,正则出现了133+两个空格导致,导致重复出现了input事件,最终经过测试,不是这个原因。

难道是我一直忽略掉的输入法的问题,测试了一下。确实是,在中文输入法中,这个问题必现,所以才有偶现中必现的结论。

是因为在中文输入法中,(此时input的值为12--用户输入数字3)从输入字符,到结束输出的过程,会依次触发以下事件。

  1. compositionstart事件
  2. input事件
  3. compositionend事件

输入123的时候,触发了input事件,input事件又会格式化输入的内容,会在123后面添加空格。 此时又触发了compositionend事件,又会空格后面添加3, 即成为123空格3, 那么就是input 和compositionend两个事件触发导致,问题出现了。

问题的解决

既然知道问题是怎么发生的了,那么好解决了。思路如下:

  1. 当用户触发compositionstart这个事件,增加flag,设置为true
  2. 触发input的时候,判断flag是否为true, 如果是true, 则不执行input里面的方法
  3. 触发compositionend这个事件,flag设置为false,再执行input里面的方法。

具体参考代码如下:

<input
  :value="value"
  @input="handleInput"
  @compositionstart="handleCompositionstart"
  @compositionend="handleCompositionend"
>
handleCompositionstart() {
  this.isLocking = true
},
handleCompositionend(event) {
  this.isLocking = false
  this.handleInputVal()
},
 handleInput(event) {
  if (this.isLocking) return
  this.handleInputVal()
}
handleInputVal () {
  // 格式化输入内容
}

​转自https://juejin.cn/post/7277797749893840937


该文章在 2025/11/6 10:13:24 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2025 ClickSun All Rights Reserved