Vue|自定义业务组件输入框

学习的过程,必定是要挑战一些复杂的页面和组件的。本来是想着写一个小demo,以提高自己的编码水平。谁知看到实现的效果之后,还是觉得有分享的价值的。并且该业务组件,在金融app中使用率应该是极高的。

通过git图描述以下该自定义业务组件的功能要求:
初始进入该页面时,输入框获取焦点。输入转账金额7876543,在输入框下方会有对应金额繁体字 柒佰捌拾柒万陆仟伍佰肆拾叁元整 与之匹配。且过万的金额汉字会呈现红色。若在输入框外任意位置点击使输入框失去焦点,输入的金额数字,会以一种金额的样式呈现即 7,876,543.00 。而当输入的转账金额以一种金额的样式呈现时,再次点击金额数字,输入框立马清空,下方匹配汉字清空隐藏。接着,在任何清空下,点击全部转入按钮,输入框会自动输入全部余额。输入框右边的清空按钮跟随输入框内容显示或隐藏。
呈上该业务组件的过程截图:
在这里插入图片描述
先观澜一下哎该组件的代码模板结构
在这里插入图片描述
解说:
第4行,<span>标签=转账金额;
第5行,<Input>标签=输入框;
第14行,<div>标签=清除输入框按钮;
第17行,<el-button>标签=全额转入按钮;
第19行,<div>标签=与输入金额数字匹配的繁体汉字;

业务逻辑代码:

<script>
// import {ToolEasy} from '../public/javascripts/index'
import ToolEasy from '../public/javascripts/ToolEasy'
export default {
  name: "li-acc-input",
  data() {
    return {
      transferNum: "",
      clickReset: false,
      textw: "",
      textm: ""
    };
  },
  watch: {
    transferNum(nInput, oInput) {
       this.callbackInput(nInput)
      if (nInput.indexOf(",") > 0) {
        // 失去焦点时触发,如果是金额格式显示,则不在进行toMoneyNum处理
        return;
      }
      // 输入框下,繁体金额匹配展示逻辑
      let thisRef = this;
      ToolEasy.capitalAcc(nInput, function (prew, postw) {
        if(!prew && !postw){
          thisRef.textw = '';
          thisRef.textm = '';
          return;
        }
        if(!postw){
          thisRef.textm = prew;
        }else {
          thisRef.textw = prew;
          thisRef.textm = postw;
        }
      })
    }
  },
  methods: {
    transferAll() {// 全额转入
      this.clickReset = true
      this.transferNum = "100";
    },
    onblur() {// 失去焦点时触发
      let thisRef = this;
     
      setTimeout(function(){
         if(thisRef.clickReset) {
          // 如果点击清除,执行拦截
          thisRef.clickReset = false
          return;
      }
        thisRef.clickReset = false;
        // 输入的数字到金额的转换
        ToolEasy.toMoneyNum(thisRef.transferNum, function(tNum){
            thisRef.transferNum = tNum
        })
      }, 222)
    },
    onFocus() {// 获取焦点时触发
      let thisRef = this;
      //如果是金额展示,获取焦点处理输入框置空
      if (thisRef.transferNum.indexOf(',') > 0) {
        thisRef.transferNum = ''
        this.$refs.infocus.focus()
      }
    },
    resetInput() {// 输入框内容清除
      this.clickReset = true;
      this.transferNum = "";
      this.$refs.infocus.focus();
    }
  },
  props: {// 属性声明,类型检查
    allBalance: {
      type: String,
      default: "0.00",
    },
    mType: {
      type: String,
      default: "转账金额",
    },
    callbackInput: {
      type: Function
    }
  }
};
</script>

代码解说

  • 当用户输入,watch:{} 中监听transferNum的变化。16行,由父组件传入的回调方法。以实时能在父组件中获取用户在子组件的输入内容。在用户输入金额同时,23行代码中方法ToolEasy.capitalAcc则会将在输入框下方,展示与用户输入的金额相匹配的繁体字。其中的回调方法,将匹配的繁体金额回调回来并赋值给组件标签。
  • 当用户输入之后,点击清除小图标,methods: {}中的方法resetInput()被触发,执行输入框内容清空且再次获取焦点。由于如果点击"清除"按钮一样达到输入框失去焦点的触发,且失去焦点的回调方法onblur() 会先于methods: {}中的方法resetInput() 执行。所以onblur()中通过定时器setTimeout以达到执行顺序有先后的效果。
  • 当用户点击全额转入,*methods: {}中的方法transferAll()*被触发,执行输入框赋值,且繁体内容随之匹配。
  • 当用胡输入金额之后,在外面点击,以致当前输入框失去焦点。methods: {}中的方法onblur()被触发。当用户为点击清除按钮时thisRef.clickReset=false,继续向下执行方法ToolEasy.toMoneyNum。将数字转换为金额样式结果回调到组件中,并进行赋值。
  • 当用输入转账金额且数字已转为金额样式7,876,543.00 对应逻辑thisRef.transferNum.indexOf(‘,’) > 0) ,此时当输入框再次获取焦点,输入框会被再次内容清空。即触发执行方法onFocus()

以上就是业务组件的功能,及实现的思想 ~
金额数字 匹配转 繁体字;金额数字 转 金额样式字符串;对应JS工具ToolEasy.js 的逻辑 :

/**
 * des: 数字 转 繁体汉字
 * acc 输入的转账金额
 * callback(prew, postw) prew:万以上金额  postw:万以下金额
 */
 const capitalAcc = (acc, callback) => {
   // 汉字数字
   const cnNums = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖']
   // 基本单位
   const cnIntRadice = ['', '拾', '佰', '仟']
   // 对应整数部分的扩展单位
   const cnIntunits = ['', '万', '亿', '兆']
   // 对应小数部分的扩展单位
   const cnDecunits = ['', '角', '分', '里']
   // 整数金额后面的字符
   const cnInteger = '整'
   // 整数之后的单位
   const cnIntLast = '元'
   // 最大处理的数字
   const maxNum = 9999999999999999.99
   // 金额整数部分
   let integerNum
   // 金额小数部分
   let decimalNum
   // 输出金额字符串
   let chineseStr = ''
   // 分离金额后,使用的数组、预定义
   let parts
  //  console.log('===capitalAcc 打印===>>> 方法进入')
   if(acc === '' || acc < 0) {
    callback('', '')
    return ''
   }

   acc = parseFloat(acc) 
   if(acc >= maxNum) {
     //如果超出最大值
     callback('', '')
     return ''
   }

   if(acc === 0){
     chineseStr = cnNums[0] + cnIntLast + cnInteger
     callback(chineseStr, '')
     return;
   }
   
  // 转换成字符串
  acc = acc.toString()
  if(acc.indexOf('.') < 0) {
    integerNum = acc
    decimalNum = ''
  } else {
    parts = acc.split('.')
    integerNum = parts[0]
    decimalNum = parts[1].substr(0, 4)
  }

  // 获取整数部分的转换
  if(parseInt(integerNum, 10) > 0) {
    let zeroCount = 0
    const IntLen = integerNum.length
    for (let i = 0; i < IntLen; i++) {
      const n = integerNum.substr(i, 1)
      const p = IntLen - i -1
      const q = p / 4
      const m = p % 4
      if (n === '0') {
        zeroCount++
      } else {
        if(zeroCount > 0) {
          chineseStr += cnNums[0]
        }
        // 归 0
        zeroCount = 0
        chineseStr += cnNums[parseInt(n)] + cnIntRadice[m]
      }

      if(m === 0 && zeroCount < 4) {
        chineseStr += cnIntunits[q]
      }
    }
    chineseStr += cnIntLast
  }

  // 小数部分
  if (decimalNum !== '') {
    const decLen = decimalNum.length
    for (let i = 0; i < decLen; i++) {
      const n = decimalNum.substr(i, 1)
      if (n !== '0') {
        chineseStr += cnNums[Number(n)] + cnDecunits[i]
      }
    }
  }

  if (chineseStr === ''){
    chineseStr += cnNums[0] + cnIntLast + cnInteger
  } else if(decimalNum === '') {
    chineseStr += cnInteger
  }

  // 如,贰拾贰万 贰仟叁佰肆拾捌元整 len=12 lastIndex = 9
  let index = chineseStr.lastIndexOf('万')
  if (index > 0) {
    let prew = chineseStr.substr(0, index+1)
    let postw = chineseStr.substr(index + 1)
    // console.log('===capitalAcc 打印1th prew, postw===>>>', prew, postw)
    callback(prew, postw)
  } else {
    // console.log('===capitalAcc 打印2th chineseStr===>>>', chineseStr)
    callback(chineseStr, '')
  }
 }

 /**
  * des: 输入的金额数字 转换 金额格式
  * acc: 输入的转账金额
  * callback(tNum) tNum:已转金额格式
  */
 const toMoneyNum = (acc, callback) => {
  // console.log('===toMoneyNum 打印===>>> 方法进入')
  if (acc) {
    if (isNaN(acc)){
      callback('')
      return ''
    }

    acc = typeof acc === 'string' ? parseFloat(acc) : acc // 判断是否是字符串,是就转数字
    acc = acc.toFixed(2)
    acc = Number.parseFloat(acc)

    acc = acc.toLocaleString() // 转换成金额显示的格式方法

    // 判断是否有小数
    if (acc.indexOf('.') < 0) {
      acc = acc + '.00'
    }
    // console.log('===toMoneyNum 打印===>>>', acc)
    callback(acc)
  }
 }

 const ToolEasy = {}
 ToolEasy.capitalAcc = capitalAcc
 ToolEasy.toMoneyNum = toMoneyNum


 export default ToolEasy
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值