layui 的 textarea 无法直接用 type="number" 或 lay-verify="number" 实现数字限制,必须通过 oninput + 正则实时清洗输入,并配合 compositionstart/end 处理中文输入法、settimeout 处理粘贴、templet 自定义模板应对表格动态渲染。

layui 的 textarea 本身不支持原生数字限制,强行套用 type="number" 会失效,必须用 JavaScript 主动拦截和清洗输入内容。
为什么不能直接用 lay-verify="number" 验证 textarea
因为 lay-verify 是表单提交时的校验逻辑,只作用于 input 类型元素;textarea 不识别 type 属性,也不触发 lay-verify="number" 的数字校验。提交前校验无法阻止用户输入字母、符号或负号——体验差,且后端仍可能收到非法值。
oninput + 正则清洗是最可靠的做法
核心思路:每次输入(含粘贴、中文输入法上屏)都实时过滤非数字字符,并处理边界情况。
- 用
oninput而不是onkeyup:能捕获粘贴、拖入、语音输入等所有变更 - 基础正则
/[^\d]/g可清除所有非数字字符,但会丢掉小数点和负号;若需支持小数,改用/[^\d.]/g,再额外控制小数点个数 - 开头多个
0(如0012)建议用.replace(/^0+(\d)/, '$1')转成12,避免无效前导零 - 若要禁止负数,加判断
if (value.startsWith('-')) value = value.slice(1),或直接在正则里排除- - 示例写法:
<textarea class="layui-textarea" oninput="this.value = this.value.replace(/[^\d]/g, '').replace(/^0+/g, '')"></textarea>
中文输入法下容易卡顿或错乱
用户用拼音打「shu zi」还没上屏时,oninput 就会触发并清洗,导致正在输入的候选字被清空。必须配合 compositionstart / compositionend:
- 监听
compositionstart时设标记isComposing = true,暂停清洗 - 监听
compositionend后再执行一次清洗逻辑 - 不要在
compositionstart中直接修改value,否则输入法状态会异常 - 粘贴场景要用
setTimeout(() => { /* 清洗 */ }, 0),确保 DOM 更新完成后再读取新值
表格中动态渲染的 textarea 需重绑事件
Layui 表格开启编辑模式时,edit: 'textarea' 是封装过的,不透传 oninput。必须放弃该配置,改用 templet 自定义模板:
- 在
templet中写完整<textarea oninput="..."></textarea> - 如果行数据是异步加载或分页重绘,每次渲染后要手动调用
layui.form.render() - 避免用全局选择器绑定事件(如
$('textarea').on('input', ...)),应绑定到具体 DOM 节点或委托到父容器
真正麻烦的不是写几行正则,而是处理中文输入法、粘贴、光标位置这三件事——漏掉任意一个,用户就会觉得“输着输着就没了”。











