React中input输入框中文输入的问题

需求:封装一个input输入组件

// Input 组件
const Input = () => {
  const handleChange = (e: any) => {
    console.log(inputValue)
  }
  return (
    <input
      type="text"
      onChange={handleChange}
    />
  )
}

export default Input

结果:问题不大,很快就撸出来了。但是使用中文输入法时,onChange事件会触发很多次,如下图:

出现这种结果的原因是拼音输入是一个过程,我们输入的每一个字母都触发了 onChange 事件。那如何处理才可以避免打印输入过程,只打印结果呢?

解决:使用 compositionEvent 事件

通过监听输入法开始输入到结束的事件,即监听 compositionstart 和 compositionend 方法,同时定义一个变量 isComposition,来判断是否处于中文输入过程当中,如果是,则不触发 onChange 后续操作。

let isComposition = false

const Input = () => {
  const handleComposition = (e: any) => {
    if (e.type === 'compositionend') {
      isComposition = false
    } else {
      isComposition = true
    }
  }
  const handleChange = (e: any) => {
    if (!isComposition) {
      const inputValue = e.target.value
      console.log(inputValue)
    }
  }
  return (
    <input
      type="text"
      onCompositionStart={handleComposition}
      onCompositionEnd={handleComposition}
      onChange={handleChange}
    />
  )
}

export default Input

你以为这样就结束了吗,并没有,在chrome浏览器输入中文没有打印结果。原因是chrome浏览器跟其他浏览器的执行顺序不同:

chrome浏览器:compositionstart -> onChange -> compositionend

非chrome浏览器:compositionstart -> compositionend -> onChange

下面针对chrome浏览器做一些特殊处理,如果是chrome浏览器,则在 compositionend 方法最后执行一次 onChange 方法,如下:

let isComposition = false
const isChrome = navigator.userAgent.indexOf('Chrome') > -1

const Input = () => {
  const handleComposition = (e: any) => {
    if (e.type === 'compositionend') {
      isComposition = false
      if (isChrome) {
        handleChange(e)
      }
    } else {
      isComposition = true
    }
  }
  const handleChange = (e: any) => {
    if (!isComposition) {
      const inputValue = e.target.value
      console.log(inputValue)
    }
  }
  return (
    <input
      type="text"
      onCompositionStart={handleComposition}
      onCompositionEnd={handleComposition}
      onChange={handleChange}
    />
  )
}

export default Input

最后测试一下:

 测试达到了预期效果,没有问题,愉快地去踩下一个坑了。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值