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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章