微信小程序原生开发获取input光标位置和监听光标位置改变问题

原创 吴就业 100 0 2024-08-12

本文为博主原创文章,未经博主允许不得转载。

本文链接:https://wujiuye.com/article/52d6077c8dcf4c88a5dfca7522afafd8

作者:吴就业
链接:https://wujiuye.com/article/52d6077c8dcf4c88a5dfca7522afafd8
来源:吴就业的网络日记
本文为博主原创文章,未经博主允许不得转载。

在做某个功能开发时,由于使用系统键盘输入找一些符号比较耗时,为了优化用户体验,我们在输入框下面提供一些快捷辅助按钮,这些按钮就是特殊符号。但是在做的过程中遇到获取光标位置的问题,因为我们需要在用户点击按钮时,在光标位置处插入特殊符号。

微信小程序如何获取input光标的位置

在官方文档中推荐了一种方式,就是通过bindinput监听输入改变,在bindinput中可以获取到新的光标位置。

<input value="{{inputValue}}" 
      bindinput="bindInputChange"/>
bindInputChange: function (e) {
    const value = e.detail.value
    const cursorPos = e.detail.cursor
    then.setData({
      	inputValue: value,
        curCursorPos: cursorPos
    })
}

但是,这只有在用户输入时,才能拿到光标。对于input失去焦点后,用户点击input重新获取焦点,怎么获取光标位置?

这个时候可以通过bindfocus监听input获取焦点事件,结合wx.getSelectedTextRange方法来获得光标位置。

<input value="{{inputValue}}" 
      bindinput="bindInputChange" bindfocus="handleFocus"/>
handleFocus: function (e) {
    const then = this
    wx.getSelectedTextRange({
      complete: res => {
        then.setData({
          curCursorPos: res.start
        })
      }
    })
  }

另外,当用户点击我们提供的按钮时,此时input会失去焦点,我们在处理辅助按钮的点击逻辑中会修改input的value,修改value后,用户点击input组件重新获取焦点时,光标还是在原来的位置。

例如:

原来input的value是:“40%✖️8”,光标位置在8的后面。

用户点击“➗”按钮,input的value变成:“40%✖️8➗”,理想情况下,用户点击input重新获取焦点时,光标位置应该在➗的后面,但实际上还是在8的后面。

怎么办呢?

我们在修改input的value的时候,是在当前光标位置处插入符号,插入后,光标位置应该+1。只是微信小程序没有提供一个可以修改光标位置的api。

要让修改的光标位置生效,需要使用input的focus+cursor属性配置在获取焦点时设置光标位置。

<input value="{{inputValue}}" 
      bindinput="bindInputChange" 
      focus="true" cursor="{{curCursorPos}}"
      bindfocus="handleFocus"/>

微信小程序如何监听光标位置改变

前面我们获取光标都是在input有输入的情况下,或者input获取到焦点的时候。

但是,如果用户获取到焦点之后,没有输入,而是移动光标,那就获取不到移动后的光标位置了。

例如,input当前输入内容“40%✖️8”,用户点击获取焦点时,光标位置在8的后面。然后用户移动光标位置到%的后面,因为用户想要在%后面输入内容,这个时候是没有api支持监听到用户移动了光标的。

那么怎么获取呢?

有个不推荐的方式可以获取到。

因为用户移动光标后,如果输入内容,那么我们就可以通过bindinput获取到新的光标位置,如果没有输入内容,而是点击了我们提供的辅助按钮,这个时候input会失去焦点,我们可以利用bindblur获取失去焦点时的光标位置。

<input value="{{inputValue}}" 
      bindinput="bindInputChange" 
      focus="true" cursor="{{curCursorPos}}"
      bindfocus="handleFocus" 
       bindblur="handleBlur"/>
handleBlur: function (e) {
    this.setData({
      curCursorPos: e.detail.cursor
    })
  },

但实际真机测试发现,辅助按钮的点击事件处理逻辑在handleBlur之前执行了,于是我想到了延迟处理点击事件。

handleKeyboardTap: function (e) {
		new Promise(resolve => {
      setTimeout(() => {
        resolve();
      }, 100); // 延迟100ms,100ms用户几乎无感知
    }).then(() => {
  		// 在这里执行辅助按钮的点击事件处理逻辑
		})
}

遗留问题

怎么在处理按钮点击事件的同时,input不会失去焦点呢?这样用户就不会每次点击辅助按钮之后,都要再点击一次input获取输入焦点了。

#前端

声明:公众号、CSDN、掘金的曾用名:“Java艺术”,因此您可能看到一些早期的文章的图片有“Java艺术”的水印。

文章推荐

SwiftUI如何阻止应用进程重启恢复到之前的状态

假如你不希望你的应用重启时,恢复到上次用户打开的窗口,而是想每次都从启动页开始。那么怎么做呢?

SwiftUI原生Chart组件如何实现鼠标移动选中才显示数值

使用SwiftUI的原生Chart组件,堆叠柱形图如何实现像网站使用ercharts实现的鼠标移动到柱状图上面才弹窗显示对应数值的效果。

SwiftUI开发macOS APP,如何自定义标题栏(TitleBar)

macOS APP应用的标题栏(TitleBar)是指包含“交通信号灯”(红黄绿三个小按钮)的一栏,通常TitleBar只包括“交通信号灯”和一个title,使用SwiftUI开发macOS APP,怎么把TitleBar隐藏掉呢?

如何将macOS app发布到app store?

开发完一个macOS app之后,我们应该如何将其发布到app store呢?这个文档记录了笔者从零开始一步步学习将自己开发好的macOS app发布到app store的过程。

如何编译构建一个同时支持多cpu架构的静态链接库(.a文件)

我想要让自己的mac OS应用支持更多用户可以使用,就必须要打出一个能同在amd64架构cpu的mac os设备上运行,也需要能在arm64架构cpu的mac os设备上运行。

使用node:alpine基础镜像今天突然就构建不了了

我的一个nextjs项目使用node:alpine基础镜像,在此之前部署到线上都能正常构建和运行,今天修改点代码提交到生产环境,发现竟然镜像构建失败了。