以 Element Plus 官网为例,直接上官网截图吧
<template>
<el-input
v-model="text"
maxlength="10"
placeholder="Please input"
show-word-limit
type="text"
/>
<div style="margin: 20px 0" />
<el-input
v-model="textarea"
maxlength="30"
placeholder="Please input"
show-word-limit
type="textarea"
/>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
const text = ref('')
const textarea = ref('')
</script>
我们可以看到,el-input 的"字符数"使用 JavaScript 字符串长度来衡量。识别的中文长度是2,其他字符是1;但是需求往往不尽如人意,某次就被我碰到了:要求中文识别的长度为2,其他符号为1。思前想后,市场上那么多昵称账号之类的,中文不都是按照1个长度来计算的吗。于是搜啊搜,还真发现了,微博账号就不一样,它识别的中文长度竟然是2,真是离离原上谱......
既然有人早早实现了,那咱也来试试吧。
<template>
<span>昵称:</span>
<el-input
v-model="nickname"
style="width: 360px"
@input="input"
placeholder="仅支持输入中英文、数字、下划线、减号"
clearable
>
<template #suffix>
<span>{{currentLen}}/30</span>
</template>
</el-input>
</template>
<script setup>
import { ref } from 'vue'
const currentLen = ref(0)
//1参数:输入的值 2参数:要限制输入的字符个数
const limitstr =(strval, strnum) =>{
let result = '';
const strleng = strval.length;
//返回字符串的总字节数
// eslint-disable-next-line no-control-regex
const byteleng = strval.replace(/[^\x00-\xff]/g, '**').length;
if (byteleng <= strnum) {
return strval;
}
for (let i = 0, bytenum = 0; i < strleng; i++) {
const byte = strval.charAt(i);
// eslint-disable-next-line no-control-regex
if (/[\x00-\xff]/.test(byte)) {
bytenum++; //单字节字符累加1
} else {
bytenum += 2; //非单字节字符累加2
}
if (bytenum <= strnum) {
result += byte;
} else {
return result;
}
}
}
// 计算字符串长度(中文算2个字符,英文、数字、减号、下划线算1个字符)
const getStringLength = (str)=> {
if (!str) {
return 0;
}
let len = 0;
for (let i = 0; i < str.length; i++) {
const char = str.charAt(i);
if (/[\u4e00-\u9fa5]/.test(char)) {
len += 2; // 中文算2个字符
} else {
len += 1; // 英文、数字、减号、下划线等算1个字符
}
}
return len;
}
const nickname = ref('')
const input = (data)=> {
// 去除非(字母/数字/下划线)字符
const filtered = data.replace(/[^\u4e00-\u9fa5a-zA-Z0-9_-]/g, '');
// 限制只能输入30个字符
nickname.value = limitstr(filtered, 30);
// 计算当前输入字符的长度
currentLen.value = getStringLength(nickname.value )
}
</script>