Vue ElementUI 输入框formatter 千分位分隔 前缀 后缀

3,302 阅读1分钟

最近接到公司一个需求,输入框输入数字,可按配置自动格式化为千分位分隔,添加相应的前缀与后缀,且保存的数据还是你输入的数据,不是格式化后的数据

所以需要自己封装一个组件,v-model绑定的值是自己输入的原始数据,el-input显示的是格式化后的数据,话不多说,直接上代码

// 组件代码
<template>
  <div>
    <el-input
      ref='oldValue'
      v-show="isFocus"
      :disabled="item.disabled"
      v-model="oldValue"
      :placeholder="item.placeholder"
      :type="item.formType"
      @blur="blur"
      @input="input"
    ></el-input>

    <el-input
      ref='formatValue'
      v-show="!isFocus"
      :disabled="item.disabled"
      v-model="formatValue"
      :maxlength="100"
      :placeholder="item.placeholder"
      @focus="focus"
    ></el-input>
  </div>
</template>

<script>
// 引入utils里面的格式化方法
import { priceFormat } from '***'
export default {
  props: {
    value: {
      type: [String, Number],
      require,
    },
    item: Object, // 传入的控制数据
  },

  data() {
    return {
      isFocus: false, // 是否处于获取焦点状态

      formatValue: '',

      oldValue: this.value,
    }
  },

  watch: {
    oldValue: {
      handler(oldValue, newValue) {
        // 是否开启千分位分割
        const openThousandth = !!this.item?.formatterSchemaDefinition.isShowThousandth
        // 前缀
        const prefix = this.item.formatterSchemaDefinition?.prefix
        // 后缀
        const suffix = this.item.formatterSchemaDefinition?.suffix
        // 小数位数
        const places = this.item?.precisions || 2

        this.formatValue = priceFormat( isNaN(this.oldValue) ? this.oldValue : Number(this.oldValue),  places, openThousandth, prefix, suffix )
      },
      immediate: true,
    },
    
    value() {
      // console.log('asdadadsadasdasdadasda')
      this.oldValue = this.value
    }
  },

  methods: {

    // 失去焦点
    blur(e) {
      // console.log('adadasdasdasdadasd')
      this.isFocus = false
      this.$emit('blur', e)
    },

    // 获取焦点
    async focus(e) {
      this.isFocus = true
      await this.$nextTick()
      // console.log(this.$refs.oldValue, 'this.$refs.oldValue')
      this.$refs.oldValue.focus()
      this.$emit('focus', e)
    },

    input() {
      console.log('qwewsfdjksdgbhjdbghjdfbj')
      this.$emit('input', this.oldValue)
    },
  },
}
</script>

// 格式化方法

/**
 * @Author: ***
 * @description: 将数字转换为金额
 * @param {*} num: 原始数据
 * @param {*} n: 保留的小数位数
 * @param {*} openThousandth: 是否开启千分位分隔
 * @param {*} prefix: 前缀
 * @param {*} suffix: 后缀
 * @return {*}
 */
export function priceFormat(num, n, openThousandth, prefix, suffix) {
  // 小数点位数
  n = n || 2
  // 分隔符
  let symbol = ","
  // num为空时,直接返回
  if (num === null || num === undefined || num === '') return num
  // 是否为小数
  let hasDot = false
  // 小数点位数
  let m = 0
  // 当开启千分位分隔且原始数据为数字时,进行千分位分隔
  if(openThousandth && typeof num == 'number') {
    if (typeof num !== 'number') throw new TypeError('num参数应该是一个number类型')
    if (n < 0) throw new Error('参数n不应该小于0')
    hasDot = parseInt(num) != num// 这里检测num是否为小数,true表示小数
    m = (n != undefined && n != null) ? n : 1
    num = m == 0 ? num.toFixed(m) + '.' : hasDot ? (n ? num.toFixed(n) : num) : num.toFixed(m)
    symbol = symbol || ','
    num = num.toString().replace(/(\d)(?=(\d{3})+\.)/g, function(match, p1, p2) {
      return p1 + symbol
    })
  }

  if (n == 0 || (!hasDot && !n)) { // 如果n为0或者传入的num是整数并且没有指定整数的保留位数,则去掉前面操作中的小数位
    num = num.substring(0, num.indexOf('.'))
  }
  return `${prefix || ''}` + num + `${suffix || ''}`
}
// 使用
<template>
    <div>
        <formatter-input :item='field' v-model="price" @input="commonChange"/>
    </div>
</template>
<script>
// 在需要使用的组件引入
import formatterInput from '***'
export default {
    components: {
        formatterInput,
      },
      data() {
          return {
              field: {
                  formatterSchemaDefinition: {
                      isShowThousandth: 1,
                      prefix: '¥',
                      suffix: '元',
                      places: 2,
                  },
                  placeholder: '请输入数据,
                  formType: 'number',
                  disabled: false
              },
              price: 0
          }
      },
      methods: {
          commonChange(e) {
              console.log(e)
          }
      }
}
</script>