elementUI 金额输入框实现

问题描述

封装一个金额输入框

问题分析

首先需要一个金额格式化的方法,可以在input输入框上覆盖一个遮罩显示格式后的金额。

组件

<template>
  <div class="m-input">
    <el-input-number
      ref="input"
      :min="curMin"
      :max="curMax"
      :controls="false"
      v-model.trim="curValue"
      @change="handleChange"
      @blur='handleBlur'
      @focus="focusInput"
      :class="clz"
      :disabled="currentDisabled"
      :placeholder="curPlaceholder"
      :precision="precision"
    ></el-input-number>
    <p v-show="showFormatPrice" @click="focusInput">{{formaterVal}}</p>
  </div>
</template>

<script>
import {formatArea, parseArea} from '@/utils/utils'

export default {
  name: 'MoneyInput',
  props: {
    value: {
      type: [String, Number],
      default: ''
    },
    placeholder: {
      type: String
    },
    max: {
      type: [String, Number],
      default: 9999999999999.99
    },
    min: {
      type: [String, Number],
      default: -9999999999999.99
    },
    clz: {
      type: String
    },
    disabled: {
      type: Boolean,
      default: false
    },
    precision: {
      type: Number,
      default: 2
    }
  },
  data() {
    return {
      currentDisabled: this.disabled,
      curPlaceholder: this.placeholder,
      curMax: this.max,
      curMin: this.min,
      curValue: this.value,
      showFormatPrice: true
    }
  },
  computed: {
    formaterVal() {
      // return formatMoney(this.curValue)
      return formatArea(this.curValue, this.precision)
    }
  },
  watch: {
    disabled(val) {
      this.currentDisabled = val
    },
    placeholder(val){
      this.curPlaceholder = val
    },
    max: {
      handler(val) {
        this.curMax = parseArea(formatArea(val, this.precision))
      },
      immediate: true
    },
    min(val){
      this.curMin = val
    },
    value: {
      handler(val) {
        if(val >= this.curMax) {
          this.curValue = this.curMax
        } else {
          this.curValue = val
        }
      },
      immediate: true
    }
  },
  methods: {
    focusInput () {
      this.showFormatPrice = false
      this.$refs.input.focus()
      if(this.curValue === 0) {
        this.curValue = undefined
      }
    },

    handleChange(val) {
      this.$emit('input', val)
    },

    handleBlur(selected){
      this.$emit('on-blur', selected)
      this.showFormatPrice = true
      // if(!this.curValue && !isNull(this.defaultVal)) {
      //   this.curValue = this.defaultVal
      // }
    }
  },
}
</script>
<style lang="scss" scoped>
  .m-input {
    position: relative;
    > p {
      position: absolute;
      top: 5px;
      left: 1px;
      height: 25px;
      line-height: 26px;
      width: 98%;
      z-index: 2;
      background: white;
      padding-left: 5px;
      border-radius: 6px;
      font-family: Arial;
      cursor: text;
      color: #464646;
      overflow: hidden;
      text-align: left;
    }

  }
</style>

export const formatArea = (num, precision = 2) => {
  if(precision < 0 || precision > 20) precision = 2
  if (parseFloat(num).toString() != "NaN") {
    // num = parseFloat((num + "").replace(/[^\d\.-]/g, "")).toFixed(precision) + ""
    num = parseFloat((num + "").replace(/[^\d\.-]/g, "")) + ""
    let left = num.split(".")[0].split("").reverse()
    let right = num.split(".")[1]
    right = right? right + '0'.repeat(20): '0'.repeat(20) // 禁止小数位进位直接截取
    right = right.substring(0, precision)
    
    let total = ""
    for (let i = 0; i < left.length; i++) {
      total += left[i] + ((i + 1) % 3 == 0 && (i + 1) != left.length ? "," : "")
    }

    let leftPart = total.split("").reverse().join("").replace(/-,/,'-')
    if(right) {
      return leftPart + "." + right
    }
    return leftPart
  }
  return ''
}

export const parseArea = (str) => {
  return parseFloat(str.replace(/[^\d\.-]/g, ""))
}

posted @ 2021-02-25 14:49  小方块的世界  阅读(3923)  评论(0编辑  收藏  举报