vue中自定義指令,限制input值為number和小數點的位數

VitoLI發表於2018-08-09

首先遇到一個問題,iOS中input設定type=number是無效的,要想實現彈出數字鍵盤,只能設定type=tel,然而問題遠遠沒有結束,type=tel是無法輸入小數點的,所以要實現限制input為number並且限制小數點的輸入,還是需要自己寫一些邏輯。

思路就是通過新增input事件監聽,通過正則判斷是否符合條件,不符合的話,要重置為上一次符合的數值。


使用方法類似於

 <input type="number"
 <!--允許 0到2位小數-->
 data-dotrange="{0,2}"
 v-model.number.trim="num"
 v-limit-input-number="num"/>
 
複製程式碼

指令的小邏輯

// limit-input-number.js

// 設定元件中的指定屬性的值
const setValue = function (exp, value, context) {
  value = isNaN(value) ? '' : value
  new Function ('context', 'value', `context.${exp} = value`)(context, value)
}
// 自定義指令
export default {
  bind (el, {expression}, {context}) {
    // 初始化lastValue
    el.lastValue = el.value

    // 通過dataset 判斷是否允許小數點
    let allowDot = !!el.dataset.dotrange
    let dotRange = el.dataset.dotrange || `{0,2}` // 預設
    let pattern = `^[0-9]+${allowDot ? `(.[0-9]${dotRange})?` : ''}$`

    if (!expression) {
      throw new TypeError('請繫結expression')
    }

    el.handleInputEvent = function (e) {
      setTimeout(() => {
        if (e.target.value === '') {
          setValue(expression, '', context)
          // 遇到非法數值,則重置
          e.target.value = ''
        } else if (e.target.value !== '' && !new RegExp(pattern).test(e.target.value)) {
          setValue(expression, parseFloat(e.target.lastValue), context)
          // 遇到非法數值,則重置為lastValue
          e.target.value = e.target.lastValue
          if (allowDot) {
          // 這個時候,根據業務邏輯,可以收起鍵盤,給出吐司提示
            e.target.blur()
            context.showToast(`小數點後最多${dotRange.replace(/[}{]/g, '').split(',')[1]}位`)
          }
        }
        e.target.lastValue = e.target.value
      }, 0)
    }
    el.addEventListener('input', el.handleInputEvent, false)
  },
  unbind (el) {
    el && el.removeEventListener('input', el.handleInputEvent, false)
  }
}

複製程式碼

相關文章