v-text-field配置maxlength校验时如何实现忽略标点计数
问题原因
原有实现无法达成效果的核心问题有3个:
- 原生
maxlength属性默认统计所有输入字符(包含标点、特殊符号),不支持自定义长度统计规则 - watch中直接替换标点的逻辑会直接删除用户输入的标点内容,和「保留输入内容、仅统计长度时排除标点」的需求不符,同时直接修改监听属性容易触发循环渲染,导致输入光标错位、输入卡顿
- 原有正则仅覆盖了少部分英文标点,中文标点(,。!?、“”等)、特殊符号完全没有被匹配到
可行方案
根据需求场景二选一即可:
方案1:保留用户输入的所有标点,仅统计长度时排除标点(推荐,符合常规交互)
不要使用原生maxlength限制,通过自定义校验规则+自定义计数实现,标点会正常保留在输入内容中,仅计算有效长度时不计入标点:
<template> <v-text-field v-model="note" dense :counter="validLength" :rules="lengthRule" hint="标点不计入长度统计,最多可输入255个有效字符" ></v-text-field> </template> <script> export default { data() { return { note: '', maxValidCount: 255 } }, computed: { // 计算排除所有标点、特殊符号后的有效长度 validLength() { if (!this.note) return 0 // \p{P}匹配全类别Unicode标点,\p{S}匹配全类别特殊符号,覆盖中英文所有标点场景 return this.note.replace(/[\p{P}\p{S}]/g, '').length }, lengthRule() { return [ () => this.validLength <= this.maxValidCount || `有效字符不能超过${this.maxValidCount}个(标点不计入长度)` ] } } } </script>
方案2:直接过滤输入内容,不允许输入标点
如果需求是不允许内容中出现标点,输入标点就自动剔除,用输入事件处理替代watch,解决光标错位问题:
<template> <v-text-field ref="noteInput" v-model="note" maxlength="255" dense @input="handleInput" ></v-text-field> </template> <script> export default { data() { return { note: '' } }, methods: { handleInput(val) { if (!val) return const inputDom = this.$refs.noteInput.$el.querySelector('input') const oldCursorPos = inputDom.selectionStart // 过滤所有标点、特殊符号 const filteredVal = val.replace(/[\p{P}\p{S}]/g, '') this.note = filteredVal this.$nextTick(() => { // 修正光标位置,避免过滤后光标自动跳到输入末尾 const beforeCursorPart = val.slice(0, oldCursorPos) const validCursorPos = beforeCursorPart.replace(/[\p{P}\p{S}]/g, '').length inputDom.setSelectionRange(validCursorPos, validCursorPos) }) } } } </script>
注意:正则使用
\p{P}和\p{S}匹配标点需要确保项目构建工具支持ES2018+ Unicode属性转义,若不支持可以替换为枚举全量中英文标点的正则:/[~!@#$%^&*()_-+=[]{};:'",.<>/?\|,。!?、;:“”‘’()【】《》……·]/g`
内容的提问来源于stack exchange,提问作者Nina
相关产品推荐
相关产品推荐

