• 限制字符的长度
  • Artiely
  • #vue
  • 2020-06-20
  • 290
  • 2 min read
  • loading...

限制字符的长度

需求

一个字母和数字算作一个字符,一个汉字算作两个字符
如:一个输入框可输入 30 个字符,同时展示剩余可输入字符
用例 1:可输入 30 个字母或数字
用例 2:只可输入 15 个汉字

开始

const charCodeDir = (c) => {
  return (c >= 0x0001 && c <= 0x007e) || (c <= 0xff9f && c >= 0xff60)
}
// 计算当前输入的字节
export function strlen(str) {
  var len = 0
  for (var i = 0; i < str.length; i++) {
    var c = str.charCodeAt(i)
    // 单字节加1
    if (charCodeDir(c)) {
      len++
    } else {
      len += 2
    }
  }
  return len
}
复制成功
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 计算还可输入的字节
export function maxlen(str, len = 60) {
  for (var i = 0; i < str.length; i++) {
    var c = str.charCodeAt(i)
    if (charCodeDir(c)) {
      // ...
    } else {
      len -= 1
    }
  }
  return len
}
复制成功
1
2
3
4
5
6
7
8
9
10
11
12
<template>
<input :maxlength="maxLength" v-model="str" ></input> 剩余{{textLen}}
</template>
<script>
import { strlen, maxlen } from '@/common/utils'
export default {
  data(){
    return {
      str
    }
  },
  computed:{
    // 输入字符的长度
    hasLen() {
      return strlen(this.str)
    },
    // 剩余字符的长度
    textLen() {
      return parseInt((30 - this.hasLen) / 2)
    },
    maxLength() {
      return maxlen(this.str)
    },
  }
}
</script>
复制成功
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

这样看起来是没问题了,手动输入也是没有什么问题,但是如果用户粘贴字符串进去就暴露问题了
用户可粘贴超过 30 个字符的内容

完善一下

<template>
<input :maxlength="maxLength" v-model="str" @change="change" ></input> 剩余{{textLen}}
</template>
<script>
import { strlen, maxlen } from '@/common/utils'
const TEXT_CHARS_LENGTH = 30
export default {
  data(){
    return {
      str
    }
  },
  computed:{
    // 输入字符的长度
    hasLen() {
      return strlen(this.str)
    },
    // 剩余字符的长度
    textLen() {
      return parseInt((TEXT_CHARS_LENGTH - this.hasLen) / 2)
    },
    maxLength() {
      return maxlen(this.str)
    },
  },
  methods:{
    change(){
      let len = strlen(this.str)
      if(len > TEXT_CHARS_LENGTH){
        this.str = this.str.substring(0, this.str - 1)
        let len2 = strlen(this.form.text)
        if (len2 > TEXT_CHARS_LENGTH) {
          this.change()
        }
      }
    }
  }
}
</script>
复制成功
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

思考

如何将此逻辑作封装成指令,方便后期同样的需求直接使用

待续。。。