怎么获取输入框当前光标的前一个字符

37 阅读3分钟

说在前面

不知道大家平时有没有遇到需要获取输入框当前光标的前一个字符的场景?今天让我们一起来看一下怎么实现这个功能。

适用场景

  • 聊天输入场景:在输入 @符号时自动触发用户选择列表
  • 代码编辑器:实现基于前一个字符的智能提示
  • 表单验证:根据前一个字符实时校验输入格式
  • 文本处理工具:实现基于上下文的自动格式化

功能实现

事件监听

<input
  @input="cursorChange"
  @keyup="cursorChange"
  @click="cursorChange"
  @mousedown="cursorChange"
/>
  • @input:监听内容变化,内容发生变化的时候需要重新获取光标位置
  • @keyup:监听键盘抬起,左右切换光标的时候需要重新获取光标位置
  • @click:监听点击操作,点击切换光标的时候需要重新获取光标位置
  • @mousedown:监听鼠标按下,点击切换光标的时候需要重新获取光标位置

光标位置计算

首先我们要先来了解一下 selectionStart 这个属性

input.selectionStart

input.selectionStart 是 HTML 输入元素(如 <input> 和 <textarea>)的一个属性,用于获取或设置输入框中选中文本的起始位置。

  • 用途:input.selectionStart 主要用于确定输入框内用户选中的文本范围的起始位置。这个位置是相对于输入框内文本的起始位置而言的,以字符为单位进行计数,索引从 0 开始。
  • 兼容性:该属性在现代浏览器中得到广泛支持,包括 Chrome、Firefox、Safari、Edge 等,是一个比较稳定和常用的属性。
  • 语法
const startPosition = inputElement.selectionStart;
inputElement.selectionStart = newStartPosition;
  • 返回值

    • 当获取 selectionStart 属性值时,返回一个整数,表示选中文本的起始位置。如果没有选中文本,该值等于光标所在的位置
    • 当设置 selectionStart 属性值时,可以传入一个整数来指定新的选中文本的起始位置

那么我们可以直接通过这个属性来获取输入框当前光标的前一个字符吗?

cursorChange(e) {
  const input = e.target;
  const value = input.value;
  const position = input.selectionStart;
  this.lastChar = value[position - 1] || "";
}
  • 输入数字

  • 输入英文

  • 输入中文

  • 输入emoji

测试了一下发现输入 emoji表情 的时候不能获取到,那我们要怎么处理这种情况呢?

字符处理机制

可以使用 Array.from() 方法将输入字符串转换为包含完整 Unicode 代码点的数组,确保每个字符(包括双字节字符)被正确分割:

const charArray = Array.from(value);

实际光标位置计算

处理因双字节字符导致的索引偏移,重新计算光标位置

let index = 0, resIndex = 0;
while (index < position) {
  index += charArray[resIndex].length;
  resIndex++;
}

完整代码

cursorChange(e) {
  const input = e.target;
  const value = input.value;
  const position = input.selectionStart;
  const charArray = Array.from(value);
  let index = 0,
    resIndex = 0;
  while (index < position) {
    index += charArray[resIndex].length;
    resIndex++;
  }
  resIndex -1;
  this.lastChar = charArray[resIndex] || "";
}

体验地址

jyeontu.xyz/JDemo/#/get…

源码

源码也上传到gitee了,有兴趣的同学也可以看看: gitee.com/zheng_yongt…

  • 🌟觉得有帮助的可以点个star~
  • 🖊有什么问题或错误可以指出,欢迎pr~
  • 📬有什么想要实现的功能或想法可以联系我~

公众号

关注公众号『前端也能这么有趣』,获取更多有趣内容。

公众号发送 加群 可以加入群聊,一起来学习(摸鱼)吧~

说在后面

🎉 这里是 JYeontu,现在是一名前端工程师,有空会刷刷算法题,平时喜欢打羽毛球 🏸 ,平时也喜欢写些东西,既为自己记录 📋,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解 🙇,写错的地方望指出,定会认真改进 😊,偶尔也会在自己的公众号『前端也能这么有趣』发一些比较有趣的文章,有兴趣的也可以关注下。在此谢谢大家的支持,我们下文再见 🙌。