vue封装金额输入的input框

前言:写vue管理系统的时候,总是会遇到金额输入框,网上找到的总是能发现一些隐蔽bug。所以小编就想能不能封装一个element-ui中el-input的金额输入框呢?

说干就干,上效果

 小编这里一共封装了5中用法,基本是够使用的了,而且是支持element属性的,好了。其他的就不说了,直接上代码。

第一步:

1.在components中新建文件夹currency,新建index.js

import Currency from './src/currency.vue'

Currency.install = function (Vue) {
  Vue.component(Currency.name, Currency)
}

export default Currency

 2.在currency中新建文件夹src,在src中间currency.vue。写入核心代码

<template>
  <sjj-input v-model="liveValue" :name="name" :placeholder="placeholder" :disabled="disabled" :readonly="readonly" @focus="handleFocus" @blur="handleBlur" @change="handleChange" v-bind="$attrs" @keydown.native="handleKeydown"></sjj-input>
</template>

<script>
import { formatter, unFormatter, numberKeyCodes, decimalKeyCodes, plusKeyCodes, minusKeyCodes, operKeyCodes } from '../../currentcy.js'
import SjjInput from 'element-ui/packages/input'
export default {
  name: 'Sjjcurrency',
  props: {
    name: 'String',
    value: {
      type: [String, Number],
      default: ''
    },
    format: {
      type: String,
      default: '16|2'
    },
    placeholder: String,
    separator: {
      type: String,
      default: ','
    },
    decimalSymbol: {
      type: String,
      default: '.'
    },
    disabled: {
      type: Boolean,
      default: false
    },
    readonly: {
      type: Boolean,
      default: false
    },
    rounding: {
      type: Boolean,
      default: false
    },
    appendKeyCodes: Array,
    preFormatter: Function
  },
  components: {
    UnInput
  },
  data () {
    return {
      hiddenValue: '', // 合法金额值
      liveValue: '' // 展示值
    }
  },
  created () {
    let userFormatVal = this.value + ''
    if (this.preFormatter) {
      userFormatVal = this.preFormatter(userFormatVal)
    }
    this.liveValue = formatter(userFormatVal + '', this.separator, this.decimalSymbol, this.format, this.integerFormat, this.rounding)
    this.hiddenValue = unFormatter(this.liveValue, this.separator)
  },
  watch: {
    value (val, oldVal) {
      let userFormatVal = this.value + ''
      if (this.preFormatter) {
        userFormatVal = this.preFormatter(userFormatVal)
      }
      this.liveValue = formatter(userFormatVal + '', this.separator, this.decimalSymbol, this.format, this.integerFormat)
      this.hiddenValue = unFormatter(this.liveValue, this.separator)
    }
  },
  methods: {
    focus () {
      let inputInner = this.$el.querySelector('.el-input__inner')
      inputInner.focus()
    },
    blur () {
      let inputInner = this.$el.querySelector('.el-input__inner')
      inputInner.blur()
    },
    select () {
      let inputInner = this.$el.querySelector('.el-input__inner')
      inputInner.select()
    },
    handleFocus (event) {
      this.liveValue = this.hiddenValue
      this.$emit('focus', event)
    },
    handleBlur (event) {
      let userFormatVal = this.liveValue
      if (this.preFormatter) {
        userFormatVal = this.preFormatter(userFormatVal)
      }
      this.liveValue = formatter(userFormatVal + '', this.separator, this.decimalSymbol, this.format, this.integerFormat, this.rounding)
      this.hiddenValue = unFormatter(this.liveValue, this.separator)
      this.$emit('input', this.hiddenValue)
      this.$nextTick(() => {
        this.$emit('blur', event)
      })
    },
    handleChange (val) {
      if (/[\u4e00-\u9fa5]/g.test(val)) { // 非IE,忽略可输入的中文
        val = this.hiddenValue
      }
      let userFormatVal = val
      if (this.preFormatter) {
        userFormatVal = this.preFormatter(val)
      }
      this.liveValue = formatter(userFormatVal + '', this.separator, this.decimalSymbol, this.format, this.integerFormat, this.rounding)
      this.hiddenValue = unFormatter(this.liveValue, this.separator)
      this.$emit('input', this.hiddenValue)
      this.$nextTick(() => {
        this.$emit('change', this.hiddenValue)
      })
    },
    handleKeydown (event) {
      if (this.readonly || this.disabled) {
        return
      }
      let keyCode = event.keyCode
      if (event.shiftKey) {
        keyCode = -9 + '' + keyCode
      }
      if (event.ctrlKey) {
        keyCode = -7 + '' + keyCode
      }
      // 获取光标位置
      let cursurPosition = 0
      let inputInner = this.$el.querySelector('.el-input__inner')
      if (inputInner) {
        if (inputInner.selectionStart !== null && inputInner.selectionStart !== undefined) {
          // 非IE、IE11
          cursurPosition = inputInner.selectionStart
        } else {
          // IE10-
          let range = document.selection.createRange()
          range.moveStart('character', -inputInner.val().length)
          cursurPosition = range.text.length
        }
      } else {
        cursurPosition = -1
      }
      keyCode = parseInt(keyCode)
      let allowKeyCodes = [
        ...numberKeyCodes,
        ...decimalKeyCodes,
        ...operKeyCodes,
        ...plusKeyCodes,
        ...minusKeyCodes
      ]
      if (this.appendKeyCodes && this.appendKeyCodes.length) {
        allowKeyCodes = allowKeyCodes.concat(this.appendKeyCodes)
      }
      // let signalKeyCodes = plusKeyCodes.concat(minusKeyCodes)
      if (allowKeyCodes.indexOf(keyCode) < 0 || (this.liveValue.indexOf('.') >= 0 && decimalKeyCodes.indexOf(keyCode) >= 0) || ((this.liveValue.indexOf('+') >= 0 || this.liveValue.indexOf('-') >= 0) && minusKeyCodes.indexOf(keyCode) >= 0) || ((this.liveValue.indexOf('+') >= 0 || this.liveValue.indexOf('-') >= 0) && plusKeyCodes.indexOf(keyCode) >= 0) || (cursurPosition > 0 && plusKeyCodes.concat(minusKeyCodes).indexOf(keyCode) >= 0)) {
        event.preventDefault()
      } else {
        if (cursurPosition === 0 && (plusKeyCodes.indexOf(keyCode) >= 0 || minusKeyCodes.indexOf(keyCode) >= 0)) {
          if ((this.liveValue.indexOf('-') < 0 && minusKeyCodes.indexOf(keyCode) >= 0) || (this.liveValue.indexOf('+') < 0 && plusKeyCodes.indexOf(keyCode) >= 0)) {
            // 123
          } else {
            event.preventDefault()
          }
        }
      }
    }
  }
}
</script>

3.currentcy.js

import { BigDecimal, RoundingMode } from 'bigdecimal'
export const numberKeyCodes = [44, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105] // 允许的数字键的keyCode
export const decimalKeyCodes = [190, 110] // 小数键的keyCode
export const plusKeyCodes = [107, -9187] // 正号的keyCode 【小键盘+, 187=(配合shift使用)】
export const minusKeyCodes = [109, 189] // 负号的keyCode
export const operKeyCodes = [9, 46, 8, 37, 39, 35, 36, -767, -786] // 操作特殊字符的KeyCode

function __getIntDigitLength__ (intDigitStr) {
  let len = {}
  let intLength = ''
  let decimalLength = ''
  intDigitStr = intDigitStr.trim()
  if (intDigitStr && intDigitStr !== '|' && /^(\d*)\|(\d*)$/g.test(intDigitStr)) {
    intLength = RegExp.$1
    decimalLength = RegExp.$2
    len.intLength = intLength
    len.decimalLength = decimalLength
    return len
  } else {
    return false
  }
}

function __getStringRegExp__ (str) {
  try {
    if (str && /[\][{}()*+?.\\^$|]/g.test(str)) {
      if (str !== '\\') return '\\' + str
      else return '\\'
    } else return str || ''
  } catch (e) {
    throw new Error('__getStringRegExp__:' + e.message)
  }
}

function __removeSeparator__ (value, separator) {
  try {
    // var _me = this
    var separatorRegExp = __getStringRegExp__(separator) || ''
    if (separatorRegExp) {
      var dh = new RegExp(separatorRegExp, 'img')
      if (value && dh.test(value)) {
        return value.replace(dh, '')
      }
    }
    return value || ''
  } catch (e) {
    throw new Error('__removeSeparator__:' + e.message)
  }
}

export function formatter (value, separator, decimalSymbol, intDigitStr, isIntegerOnly, rounding) {
  try {
    // let valueValid = false
    var _currencyValue = {
      intLength: '16',
      decimalLength: '2',
      NegativeValue: '',
      intValue: '',
      decimalValue: '',
      formatValue: ''
    }
    value = value + ''
    if (!value || value === '-' || value === '+') {
      return ''
    }
    // var _me = this,
    var separatorRegExp, _value, __decimalLen, __intLen // 整数部分
    var lenObj = __getIntDigitLength__(intDigitStr)
    if (lenObj) {
      _currencyValue.intLength = lenObj.intLength
      _currencyValue.decimalLength = lenObj.decimalLength
    }
    __intLen = parseInt(_currencyValue.intLength, 10)
    __decimalLen = rounding ? parseInt(_currencyValue.decimalLength, 10) + 1 : parseInt(_currencyValue.decimalLength, 10)

    // var isNegative = false // 是否负数
    var valArr = /^-([^-]+)$/.exec(value)
    if (valArr) {
      // isNegative = true // 表示是负数
      _currencyValue.NegativeValue = '-'
      value = valArr[1]
    }

    if (separator === '') {
      return ''
    }

    _value = value // 整数部分
    _currencyValue.decimalValue = '' // 小数部分
    if (value.indexOf('.') > -1) { // 若含有小数点,则处理得到整数部分和小数部分
      _currencyValue.decimalValue = value.substring(value.indexOf('.') + 1)
      _value = value.substring(0, value.indexOf('.'))
    }
    // 若未输入整数部分,则自动取成0----------------------------------------------------
    _value = _value === '' ? '0' : _value
    // _value === '' ? _value = '0' : _value = _value

    if (separator !== '') {
      separatorRegExp = __getStringRegExp__(separator)
      _value = __removeSeparator__(_value, separator) // 去分隔符
    }
    if (isNaN(_value) || isNaN(_currencyValue.decimalValue)) { // 若不是数字则报错,isNaN('')=false
      return ''
    }
    // modify begin
    if (isIntegerOnly && value.indexOf('.') < 0) { // 纯整数格式化且不含.时,对纯整数进行格式化
      if (_currencyValue.decimalLength !== '') {
        if (_value.length > __decimalLen) {
          _currencyValue.decimalValue = _value.substring(_value.length - __decimalLen)
          _value = _value.substring(0, _value.length - __decimalLen)
        } else {
          var _s = _value
          for (var i = 0; i < (__decimalLen - _value.length); i++) {
            _s = '0' + _s
          }
          _currencyValue.decimalValue = _s
          _value = '0'
        }
      } else {
        _currencyValue.decimalValue = ''
      }
    } else {
      if (_currencyValue.decimalLength !== '') {
        if (_currencyValue.decimalValue.length < __decimalLen) {
          var _d = _currencyValue.decimalValue
          for (var j = 0; j < (__decimalLen - _currencyValue.decimalValue.length); j++) {
            _d += '0'
          }
          _currencyValue.decimalValue = _d
        } else {
          if (_currencyValue.decimalValue.length > __decimalLen) {
            // valueValid = false
          }
          _currencyValue.decimalValue = _currencyValue.decimalValue.substring(0, __decimalLen)
        }
      }
    }
    // modify end

    var _intVal = _value
    if (_currencyValue.intLength !== '') { // 若存在整数位的限制
      if (_currencyValue.intLength < _intVal.length) {
        // valueValid = false
      }
      _intVal = _intVal.substring(0, __intLen)
    }
    _currencyValue.intValue = _value = _intVal
    // 整数处理完毕 end
    var _digitpoint = (_currencyValue.decimalValue ? decimalSymbol : '')
    let zeroFilter = (_currencyValue.intValue + '').split('').filter(x => {
      return x !== '0'
    })
    if (zeroFilter.length === 0) { // 输入所有位数都是0的情况,设置后直接返回
      _currencyValue.intValue = '0'
      let zeroFilterDec = (_currencyValue.decimalValue + '').split('').filter(x => {
        return x !== '0'
      })
      // 去掉输入全部为0时的负号
      if (zeroFilterDec.length === 0) {
        _currencyValue.NegativeValue = ''
      }

      _currencyValue.formatValue = _currencyValue.NegativeValue + '0' + (_currencyValue.decimalValue !== '' ? (_digitpoint + _currencyValue.decimalValue) : '')
      if (rounding) {
        _currencyValue.formatValue = new BigDecimal(_currencyValue.formatValue).setScale(__decimalLen - 1, RoundingMode.HALF_UP()).toString()
      }
      return _currencyValue.formatValue
    }
    // 处理整数的前缀0
    if (/^0+/g.test(_currencyValue.intValue) && !(/^(0+)$/g.test(_currencyValue.intValue)) && !(/^0$/g.test(_currencyValue.intValue))) {
      _currencyValue.intValue = _currencyValue.intValue.replace(/^0+/, '')
      _value = _intVal = _currencyValue.intValue
    }

    if (rounding) {
      let rVal = _value + _digitpoint + _currencyValue.decimalValue
      let roundingVal = new BigDecimal(rVal).setScale(__decimalLen - 1, RoundingMode.HALF_UP()).toString()
      _value = roundingVal.substring(0, roundingVal.indexOf(_digitpoint))
      _currencyValue.decimalValue = roundingVal.substring(roundingVal.indexOf(_digitpoint) + 1)
    }

    // 整数部分的分隔符处理开始
    if (separator !== '') {
      _value = _value + separator
      var re = new RegExp('(\\d)(\\d{3}' + separatorRegExp + ')') // 以3个字符串为一组
      while (re.test(_value)) {
        _value = _value.replace(re, '$1' + separator + '$2')
      }
      _value = _value.replace(new RegExp(separatorRegExp + '$'), '') // 去掉末尾的分隔符
    }
    _currencyValue.formatValue = _currencyValue.NegativeValue + _value + (_currencyValue.decimalValue !== '' ? (_digitpoint + _currencyValue.decimalValue) : '')
    if (+_currencyValue.formatValue < 0) {
      // 去除-号
      return _currencyValue.formatValue.substr(1)
    } else {
      return _currencyValue.formatValue
    }
    // return _currencyValue.formatValue
  } catch (e) {
    throw new Error('formatter', e.message)
  }
}
export function unFormatter (value, separator) {
  return (value + '').replace(new RegExp(separator, 'ig'), '')
}

4.然后就是最愉快的代码引入了

<currency ref="cry1" v-model="num" :format="format" placeholder="请输入内容" @change="handleChange"/>

 5.具体的方法

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,下面是一个基于 Vue 的单选组件实现,可以通过 `options` 和 `value` 属性来设置选项和选中的值: ```vue <template> <div> <label v-for="option in options" :key="option.value"> <input type="radio" :value="option.value" :checked="value === option.value" @change="handleChange(option.value)"> {{ option.label }} </label> </div> </template> <script> export default { props: { options: { type: Array, required: true }, value: { type: String, required: true } }, methods: { handleChange(newValue) { this.$emit('input', newValue); } } } </script> ``` 在该组件中,我们使用 `v-for` 来循环渲染每个选项,并根据 `value` 属性来确定当前选中的选项。当用户选择某个选项时,我们会触发 `@change` 事件,并将新的选项值通过 `$emit` 方法传递出去。 你可以在父组件中使用该组件,并通过 `v-model` 指令来绑定选中的值,示例代码如下: ```vue <template> <div> <radio-button :options="options" v-model="selectedOption" /> </div> </template> <script> import RadioButton from './RadioButton.vue'; export default { components: { RadioButton }, data() { return { options: [ { value: 'option1', label: 'Option 1' }, { value: 'option2', label: 'Option 2' }, { value: 'option3', label: 'Option 3' }, ], selectedOption: 'option1' }; } } </script> ``` 在上述示例中,我们将选项数组和选中的值都定义在了父组件的 `data` 中,并将 `selectedOption` 绑定到 `RadioButton` 组件的 `v-model` 上,从而实现了父子组件之间的双向数据绑定。当用户选择某个选项时,`selectedOption` 的值会自动更新,反之亦然。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

shuleijia

您的鼓励是我最大的创作动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值