输入框的输入长度限制不是我想要的

137 阅读2分钟

以 Element Plus 官网为例,直接上官网截图吧

image.png

<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,真是离离原上谱......

image.png

既然有人早早实现了,那咱也来试试吧。

<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>

image.png