textarea,input輸入字符數限制。

textarea,input輸入字符數限制。

  在作開發時,有一種需求是對輸入框(input,textarea)的字數作限制。若是按照JS的規定,字符串裏全部的字符,長度都是1。可是有時候咱們須要實現文本框中輸入中文長度是2(或是3),其餘非中文輸入是1。這個時候就須要本身寫一段代碼來判斷:html

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


接下來就是對輸入的字符串長度進行限制:算法

  在input和textarea中,輸入的長度限制須要添加maxlength屬性。一般狀況下,只要給maxlength一個固定的值就能解決問題。可是這裏因爲咱們的中文預設長度是2。因此maxlegth的值應該是動態設置的。
  
  我用vue來寫,只要在模板中給maxlength綁定一個值:npm

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

  vue watch監聽剩餘字數,並截斷多出的字符。由於中文輸入法的在非正式輸入時,對於咱們這個算法,會出現剩餘字符數爲負值的狀況。因此須要增長如下代碼,在輸入數量超過期截斷。ui

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

最終效果:this

圖片描述

完整demo(vue寫的):spa

<!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>
相關文章
相關標籤/搜索