textarea,input输入字符数限制。

textarea,input输入字符数限制。

  在做开发时,有一种需求是对输入框(input,textarea)的字数做限制。如果按照JS的规定,字符串里所有的字符,长度都是1。但是有时候我们需要实现文本框中输入中文长度是2(或是3),其他非中文输入是1。这个时候就需要自己写一段代码来判断:

function getStringLengthForChinese (val) {
    let str = val.toString()
    let bytesCount = 0
    for (let i = 0, len = str.length; i < len; i++) {
      let c = str.charCodeAt(i)
      if ((c > 0x0001 && c <= 0x007e) || (c >= 0xff60 && c <= 0xff9f)) { //这里是16进制表示,也可以用十进制
        bytesCount = bytesCount + 1
      } else {
        bytesCount = bytesCount + 2
      }
    }
    return bytesCount
  }

这样就实现了获取一段字符串的长度,中文为2。


接下来就是对输入的字符串长度进行限制:

  在input和textarea中,输入的长度限制需要添加maxlength属性。通常情况下,只要给maxlength一个固定的值就能解决问题。但是这里由于我们的中文预设长度是2。所以maxlegth的值应该是动态设置的。
  
  我用vue来写,只要在模板中给maxlength绑定一个值:

       <textarea :maxlength="maxlegth" 
       @input="textareaChange($event)"
       ></textarea>
       
       <span>还可以输入{{codeNum}}个字符</span>

 maxlegth需要给定一个预设值。
 下面是限制字符输入数量的方法:

function computedLen(str, totalLength, maxLength) {
  let rep = /[0-9a-zA-Z|\s]/ // 正则判断字母数字
  let strArr = str.split('')
  let totalLen = totalLength// 总的输入长度
  let maxLen = maxLength// input或textarea上maxlength的值,这里由于中文算2个占位,所以传入的maxLength应该为totalLength的一半
  let len = 0 // 已经输入的字符数
  let leftLen = 0 // 剩余可输入字符数

  strArr.forEach((val,key) => {
    if (rep.test(val)) {
      leftLen = Math.ceil(totalLen - len * 2)// 剩余输入数等于总长 - 输入数,乘以2是因为非中文的len只算0.5
      if (leftLen === 0) {
        return false // 如果剩余数是0,就退出循环,不能输入了
      }
      len = len + 0.5// 如果输入非中文,算加半个字符,maxlengtrh也加0.5,这样就实现了两个非中文长度等于一个中文
      maxLen = maxLen + 0.5
    } else {
      len = len + 1
    }
  })
  return {
    maxLen: Math.ceil(maxLen) // 返回我们需要的maxlegt的值
  }
}

function textareaChange (e) {
        setTimeout(() => {
          let count = this.computedLen(e.target.value, 30, 15)
          this.maxLength = count.maxLen
        }, 200)
      }

  上面代码的关键在于获取maxlength的值。这个值是动态的,在只输入中文的情况下,这个值等于我们的预设值,如果输入两个非中文,maxlength就会动态的加1。

  vue watch监听剩余字数,并截断多出的字符。因为中文输入法的在非正式输入时,对于我们这个算法,会出现剩余字符数为负值的情况。所以需要增加以下代码,在输入数量超过时截断。

watch: {
      'title' () {
        this.codeNum = 30 - this.getStringLengthForChinese(this.title)
        if (getStringLengthForChinese(this.title) > 30) {//如果占位数大于30
          let arr = this.title.split('')// 输入字符串转为数组,依次推出最后一位元素
          for (let i = arr.length - 1; i >= 0; i--) {
            arr = arr.slice(0, i)// 每推出一个,将数组转为字符串,做一次占位数判断
            this.title = arr.join('')
            if (getStringLengthForChinese(this.title) <= 30) {
              break
            }
          }
        }
      }
    }

最终效果:

图片描述

完整demo(vue写的):

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<div id="app">
  <textarea :maxlength="maxLength" v-model="title" @input="textareaChange($event)"></textarea>

  <span>还能输入{{codeNum}}</span>
</div>

<body>

</body>
<script>
  new Vue({
    el: '#app',
    data() {
      return {
        title: '',
        maxLength: 15,
        codeNum: 30
      }
    },
    methods: {
      getStringLengthForChinese(val) {
        let str = val.toString()
        let bytesCount = 0
        for (let i = 0, len = str.length; i < len; i++) {
          let c = str.charCodeAt(i)
          if ((c > 0x0001 && c <= 0x007e) || (c >= 0xff60 && c <= 0xff9f)) { //这里是16进制表示,也可以用十进制
            bytesCount = bytesCount + 1
          } else {
            bytesCount = bytesCount + 2
          }
        }
        return bytesCount
      },
      textareaChange(e) {
        setTimeout(() => {
          let count = this.computedLen(e.target.value, 30, 15)
          this.maxLength = count.maxLen
        }, 200)
      },
      computedLen(str, totalLength, maxLength) {
        let rep = /[0-9a-zA-Z|\s]/ // 正则判断字母数字
        let strArr = str.split('')
        let totalLen = totalLength // 总的输入长度
        let maxLen = maxLength // input或textarea上maxlength的值,这里由于中文算2个占位,所以传入的maxLength应该为totalLength的一半
        let len = 0 // 已经输入的字符数
        let leftLen = 0 // 剩余可输入字符数

        strArr.forEach((val, key) => {
          if (rep.test(val)) {
            leftLen = Math.ceil(totalLen - len * 2) // 剩余输入数等于总长 - 输入数,乘以2是因为非中文的len只算0.5
            if (leftLen === 0) {
              return false // 如果剩余数是0,就退出循环,不能输入了
            }
            len = len + 0.5 // 如果输入非中文,算加半个字符,maxlengtrh也加0.5,这样就实现了两个非中文长度等于一个中文
            maxLen = maxLen + 0.5
          } else {
            len = len + 1
          }
        })
        return {
          maxLen: Math.ceil(maxLen) // 返回我们需要的maxlegt的值
        }
      }

    },
    watch: {
      'title' () {
        this.codeNum = 30 - this.getStringLengthForChinese(this.title)
        if (getStringLengthForChinese(this.title) > 30) { //如果占位数大于30
          let arr = this.title.split('') // 输入字符串转为数组,依次推出最后一位元素
          for (let i = arr.length - 1; i >= 0; i--) {
            arr = arr.slice(0, i) // 每推出一个,将数组转为字符串,做一次占位数判断
            this.title = arr.join('')
            if (getStringLengthForChinese(this.title) <= 30) {
              break
            }
          }
        }
      }
    }
  })
</script>

</html>
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值