浏览器端实现类似input限制输入两位小数,输入时光标从输入位置移动到最后
1.问题描述展示
示例代码所做限制为不允许输入字母d,其他限制规则可以根据需求自己调整,使用React编写,其他框架或原生均可根据该代码理解原理进行转变,特意使用了中文键盘可以看到输入框下面白色框闪出,就是我按下了键盘d键
1) gif图示例
2)代码
import { useState } from "react"
export default function () {
const [value, setValue] = useState(1234)
const onChange = (e) => {
const inputValue = e.nativeEvent.target.value
const value = inputValue.replace('d', '')
setValue(value)
}
return <div style={{marginTop:200}}>
<h3>焦点修改实例:不允许输入字母 d 无处理情况</h3>
<input value={value} onChange={onChange}></input>
</div>
}
3)原因分析
假设目前输入值为1234,光标移动到2后面并输入字母d ,此时输入框得到的输入值为12d34,而我们通过代码将本来应该是12d34的值修改为了1234,也就导致了光标定位到了最后一位
之所以这样处理,猜想大概是因为通过代码进行值的修改的时候存在多种情况比如
a. 1234 => 12456 位数增多
b. 1234 => 12 位数变少
c. 1234 => 5678 值全变化
浏览器实现时为了统一这种情况 只要当浏览器输入框获取的输入值与设置的值不等的时候都重置光标位置
react使用value对输入框输入值做控制的流程为: (以输入框已经输入1234 光标移动到2后面输入d为例)
1.按下d键
2.输入框获得值12d34,但是此时输入框的值受value控制,onChange事件中如果不对value做修改则不会改变输入框实际展示值 (也就是说12d34浏览器输入框内部已经获取到的值为12d34,只是页面并未变化,页面变化由input上的value控制)
3.输入框onChang事件触发,此时代码处理,会将输入框获取值由本应该设置为12d34,修改为了1234,光标重置到最后面 (即输入框内部获取的值如果不等于value值就会光标重置到最后面)
2.解决方案
1)宏任务延时处理
原理为通过input.setSelectionRange改变光标位置,具体api细节自行百度参考文档
import { useState } from "react"
export default function () {
const [value1, setValue1] = useState(1234)
const onChange1 = (e) => {
const start = e.target.selectionStart
const inputValue = e.nativeEvent.target.value
const value = inputValue.replace('d', '')
const input = e.nativeEvent.target
setValue1(value)
setTimeout(() => {
inputValue.includes('d') && input.setSelectionRange(start - 1, start - 1)
}, 0)
}
return <div style={{marginTop:200}}>
<h3>焦点修改实例:不允许输入字母 d 宏任务处理</h3>
<input value={value1} onChange={onChange1}></input>
</div>
}
虽然能够让光标位置正确,但是多次输入的时候存在光标从最后面移动到原位置的情况
2) 微任务处理(关于微任务宏任务可以自行百度了解)
import { useState } from "react"
export default function () {
const [value2, setValue2] = useState(1234)
const onChange2 = (e) => {
const start = e.target.selectionStart
const inputValue = e.nativeEvent.target.value
const value = inputValue.replace('d', '')
const input = e.nativeEvent.target
setValue2(value)
new Promise(res => {
res()
// promist.then的回调函数属于微任务
}).then(() => {
inputValue.includes('d') && input.setSelectionRange(start - 1, start - 1)
})
}
return <div style={{marginTop:200}}>
<h3>焦点修改实例:不允许输入字母 d 微任务处理</h3>
<input value={value2} onChange={onChange2}></input>
</div>
}
3.总结
输入框onChange修改value值导致的光标定位到最后的时机在微任务和宏任务的前面,
即 顺序为 1.重置光标 => 2.微任务 =>(浏览器内部重置光标)界面重新渲染 => 3.宏任务
其中使用宏任务二者执行间隔时间跨度大,导致重置光标界面已经发生变化,宏任务执行恢复光标,导致看到光标从最后移动到代码设置的位置(即:浏览器执行恢复光标 =>界面重新渲染 ,光标移动到最后 => 代码设置光标位置 => 浏览器重新渲染,恢复到代码设置的位置)
微任务则缩小了间隔或者说顺序 (即:浏览器执行恢复光标 => 代码设置光标位置 => 浏览器重新渲染,设置为代码设置的位置)
但是该代码仅仅处理了简单的情况即每次只输入一位的情况,还存在一些边界情况未处理,例如直接复制dddd,调整输入位置,粘贴就会导致光标位置后移,此种情况就需要对原值与新输入值做对比并进行处理
浏览器端实现类似input限制输入两位小数,输入时光标从输入位置移动到最后的更多相关文章
- input和React-Native的TextInput的输入限制,只能输入两位小数(阻止0开头的输入),类似价格限制
一.背景: 想要实现一功能: 1. 最多只能输入两位小数,类似的价格限制 2. 实时监听限制输入,禁止输入不符合规范的字符(当输入违禁字符,进行删除操作) 这样做的优点: 1. 在用户输入时直接进行限 ...
- Android限定EditText的输入类型为数字或者英文(包括大小写),EditText,TextView只能输入两位小数
Android限定EditText的输入类型为数字或者英文(包括大小写) // 监听密码输入框的输入内容类型,不可以输入中文 TextWatcher mTextWatcher = new Tex ...
- OC UITextField只允许输入两位小数
//只能输入两位小数 - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range r ...
- angularjs控制输入框只输入数字及最多输入两位小数
ps:示例中作用在循环中,其它的你可以按实际需求进行修改使用 <input type="text" ng-model="item.productNumber&quo ...
- 转载:html+js实现只允许输入两位小数的输入框
JS代码: <script language="JavaScript" type="text/javascript"> function clear ...
- 【devexpress】spinEdit控件如何设置只能输入两位小数
只需设置对应的正则表达式即可,我这里设置的是n2意思就是两位小数的意思 效果如下
- ios TextField限制输入两位小数
只需要实现textField的这个代理方法就可以实现 - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange: ...
- 【前端开发】限制input输入保留两位小数
<input type="text" name='amount' id="cash_num" placeholder="请输入金额" ...
- 【jQuery、原生】键盘键入两位小数
jquery的处理办法 <!doctype html> <html lang="en"> <head> <meta charset=&qu ...
- codevs 1206 保留两位小数
http://codevs.cn/problem/1206/ 1206 保留两位小数 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 青铜 Bronze 题解 查看运行结果 ...
随机推荐
- iMindMap 10 的使用体验 + 讯飞输入法 + windows防火墙 (完美)
这个软件 最终的效果非常好. 但是有一个硬bug,就是输入光标 搜狗输入法和百度输入法,输入法获取不到,导致输入中文的时候,文字候选框位置特别远. 如果是纯英文 输入使用,就没有这个bug. 总结: ...
- Java加密技术(三)——PBE算法
Javapbe对称加密 除了DES,我们还知道有DESede(TripleDES,就是3DES).AES.Blowfish.RC2.RC4(ARCFOUR)等多种对称加密方式,其实现方式大同小 ...
- Ubuntu 14.04 升级到Gnome3.12z的折腾之旅(警示后来者)+推荐Extensions.-------(一)
PS:要转载请注明出处,本人版权所有. PS: 这个只是基于<我自己>的理解, 如果和你的原则及想法相冲突,请谅解,勿喷. 前置说明 本文发布于 2014-12-19 22:40:20 ...
- spring boot2集成api文档工具swagger-ui(上)
说明 第一步:创建项目 浏览器打开:https://start.spring.io/,生成一个spring boot项目 点击Generate这个按钮,下载项目包文件 第二步:导入开发工具 打开下载目 ...
- [bzoj2120]数颜色/维护队列 (分块)
数颜色/维护队列 [做题笔记] 此生第一道不贺题解\(AC\)的分块蓝题!!! 题目描述 墨墨@hs_mo购买了一套 \(N\) 支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨 ...
- 3DCAT实时云渲染助力VR虚拟现实迈向成熟
近年来,虚拟现实(Virtual Reality, VR)技术在市场上的应用越来越广泛,虚拟现实已成为一个热门的科技话题.相关数据显示,2019年至2021年,我国虚拟现实市场规模不断扩大,从2019 ...
- UE干货| UE虚幻引擎调试神器—控件反射器
一.打开控件反射器 可以通过窗口→开发者工具→控件反射器 打开: 也可以在umg编辑器上方控件反射器打开. 二.UE控件反射器使用方法 运行项目后,点击控件反射器的"选择可测试命中控件&qu ...
- 06.Android之消息机制问题
目录介绍 6.0.0.1 谈谈消息机制Hander作用?有哪些要素?流程是怎样的? 6.0.0.2 为什么一个线程只有一个Looper.只有一个MessageQueue,可以有多个Handler? 6 ...
- 记录--form 表单恢复初始数据
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 form 表单恢复初始数据 在现代的 Web 开发中,表单是不可或缺的组件之一.用户可以通过表单输入和提交数据,而开发者则需要对这些数据进 ...
- Lambda表达式编写递归函数
class Program { //Fix求出的是函数f的不动点,它就是我们所需要的递归函数: static Func<T, TResult> Fix<T, TResult>( ...