vue指令實(shí)現(xiàn)數(shù)字和大寫中文實(shí)時互轉(zhuǎn)
說在前面
最近在做一個需求,需要在用戶輸入數(shù)字失焦后實(shí)時將數(shù)字轉(zhuǎn)為大寫中文,聚焦的時候?qū)⒋髮懼形霓D(zhuǎn)為數(shù)字以便用戶繼續(xù)修改。這里我們可以封裝一個通用指令來做轉(zhuǎn)換,接下來就讓我們一起來實(shí)現(xiàn)一個轉(zhuǎn)換指令吧。
效果展示
體驗(yàn)地址
jyeontu.xyz/jvuewheel/#/JNumberToChineseWordsView
實(shí)現(xiàn)思路
1、數(shù)字轉(zhuǎn)大寫中文
首先我們需要先實(shí)現(xiàn)一個函數(shù),將數(shù)字轉(zhuǎn)為大寫中文的形式。
(1)函數(shù)入?yún)?/strong>
const numberToChineseWords = (num, unit = "元", append = "整") => {...};
1.num
必出參數(shù),默認(rèn)值為 “元”,需要進(jìn)行轉(zhuǎn)換的數(shù)字。
2.unit
可選參數(shù),默認(rèn)值為 “元”,用于指定整數(shù)金額部分后面跟隨的單位字符。通過設(shè)置這個參數(shù),可以根據(jù)不同的業(yè)務(wù)場景或語言習(xí)慣需求來改變金額單位的顯示,比如在某些特定財務(wù)報表中可能需要顯示為 “圓” 等情況,就可以傳入相應(yīng)的字符作為該參數(shù)的值進(jìn)行自定義。
3.append
可選參數(shù),默認(rèn)值為 “整”,用于在金額為整數(shù)時,在轉(zhuǎn)換后的中文金額表述后面追加的字符。比如常見的整數(shù)金額書寫規(guī)范中會添加 “整” 字表示沒有小數(shù)部分,若不需要這個追加字符或者有其他業(yè)務(wù)特定的追加內(nèi)容要求,可以通過修改該參數(shù)來實(shí)現(xiàn)。
(2)輔助常量
用于輔助完成數(shù)字到中文的轉(zhuǎn)換。
// 漢字的數(shù)字 const cnNums = ["零", "壹", "貳", "叁", "肆", "伍", "陸", "柒", "捌", "玖"]; // 基本單位 const cnIntRadice = ["", "拾", "佰", "仟"]; // 對應(yīng)整數(shù)部分?jǐn)U展單位 const cnIntUnits = ["", "萬", "億", "兆"]; // 對應(yīng)小數(shù)部分單位 const cnDecUnits = ["角", "分", "毫", "厘"]; // 最大處理的數(shù)字 const maxNum = 9999999999999999.99;
(3)輸入?yún)?shù)合法性檢查與預(yù)處理
- 首先對傳入的 num 參數(shù)進(jìn)行空字符串檢查,如果為空,則直接返回空字符串,避免后續(xù)不必要的處理。
- 若轉(zhuǎn)換后的金額大于 maxNum,超出了函數(shù)能夠合理處理的范圍,同樣返回空字符串,確保函數(shù)的穩(wěn)定性和正確性。
- 對于金額為 0 的特殊情況,直接按照設(shè)定的格式(使用默認(rèn)或傳入的 unit 和 append 參數(shù))構(gòu)建并返回對應(yīng)的中文金額表示,如 “零元整”(默認(rèn)參數(shù)情況)。
(4)整數(shù)部分轉(zhuǎn)換邏輯
if (parseInt(integerNum, 10) > 0) { let zeroCount = 0; let IntLen = integerNum.length; for (let i = 0; i < IntLen; i++) { let n = integerNum[i]; let p = IntLen - i - 1; let q = p / 4; let m = p % 4; if (n === "0") { zeroCount++; } else { if (zeroCount > 0) { chineseStr += cnNums[0]; } // 歸零 zeroCount = 0; chineseStr += cnNums[parseInt(n)] + cnIntRadice[m]; } if (m === 0 && zeroCount < 4) { chineseStr += cnIntUnits[q]; } } chineseStr += unit; }
- 當(dāng)整數(shù)部分?jǐn)?shù)字(通過
parseInt(integerNum, 10)
判斷)大于0
時,進(jìn)入一個循環(huán)來處理整數(shù)部分的每一位數(shù)字。 - 在循環(huán)中,對于每一位數(shù)字,先獲取其對應(yīng)的數(shù)字字符
n
,并計算該位數(shù)字在整個整數(shù)金額中的位置信息,包括距離個位的位數(shù)p
、所在的四位一組中的位置索引m
以及對應(yīng)的擴(kuò)展單位層級q
。 - 如果當(dāng)前位數(shù)字是
0
,則記錄連續(xù)0
的個數(shù)zeroCount
,用于后續(xù)判斷是否需要添加 “零
” 字來正確表示中文金額的讀法。當(dāng)遇到非0
數(shù)字時,如果之前有連續(xù)的0
,則先在chineseStr
中添加 “零
” 字進(jìn)行合理的中文表述銜接,并將zeroCount
歸零。然后根據(jù)當(dāng)前數(shù)字和對應(yīng)的基本單位cnIntRadice[m]
構(gòu)建出如 “叁佰
” 這樣的部分金額表述添加到chineseStr
中。此外,當(dāng)當(dāng)前位處于每四位一組的個位位置(即m === 0
)且連續(xù)0
的個數(shù)小于4
時,添加對應(yīng)的擴(kuò)展單位cnIntUnits[q]
到chineseStr
中,例如添加 “萬
”“億
” 等字。循環(huán)結(jié)束后,在chineseStr
末尾添加unit
(即整數(shù)金額對應(yīng)的單位字符)。
(5)小數(shù)部分轉(zhuǎn)換邏輯
if (decimalNum !== "") { let decLen = decimalNum.length; for (let i = 0; i < decLen; i++) { let n = decimalNum[i]; if (n !== "0") { chineseStr += cnNums[Number(n)] + cnDecUnits[i]; } } }
對于小數(shù)部分,如果 decimalNum
不為空字符串,說明存在小數(shù)金額需要轉(zhuǎn)換。通過循環(huán)遍歷小數(shù)部分的每一位數(shù)字,當(dāng)數(shù)字不為 0
時,將對應(yīng)的中文數(shù)字(通過 cnNums[Number(n)]
獲?。┖拖鄳?yīng)的小數(shù)單位(cnDecUnits[i]
)組合添加到 chineseStr
中,構(gòu)建出小數(shù)金額的中文表示形式,比如將 0.34
中的 3
轉(zhuǎn)換為 “叁角
” 添加到字符串中。
(6)最終結(jié)果處理與返回
if (chineseStr === "") { chineseStr += cnNums[0] + unit + append; } else if (decimalNum === "") { chineseStr += append; } return chineseStr;
最后,需要根據(jù) chineseStr
的情況進(jìn)行一些補(bǔ)充處理。如果 chineseStr
為空(可能是傳入的金額為 0
且經(jīng)過前面邏輯處理后為空字符串等情況),則按照設(shè)定的格式(使用 unit
和 append
參數(shù))構(gòu)建并返回對應(yīng)的中文金額表示,如 “零元整
”。如果小數(shù)部分 decimalNum
為空,表示金額是整數(shù),就在 chineseStr
后面添加 append
(默認(rèn)是 “整” 字)。
(7)轉(zhuǎn)換測試
1024
numberToChineseWords(1024) //壹仟零貳拾肆元整
99999999
numberToChineseWords(99999999) //玖仟玖佰玖拾玖萬玖仟玖佰玖拾玖元整
12345.6789
numberToChineseWords(12345.6789) //壹萬貳仟叁佰肆拾伍元陸角柒分捌毫玖厘
2、指令實(shí)現(xiàn)
export default { bind: function (el, binding) { const params = binding.value || {}; const { unit = "", append = "" } = params; let originVal = el.innerText; if (el.innerHTML) { el.innerHTML = numberToChineseWords(el.innerText, unit, append); } el.addEventListener("focus", (event) => { event.target.value = originVal; }); el.addEventListener("blur", (event) => { const value = event.target.value; originVal = value; event.target.value = numberToChineseWords(value, unit, append); }); }, };
(1)參數(shù)解構(gòu)與默認(rèn)值設(shè)置
在 bind
函數(shù)中,首先通過 binding.value
獲取指令綁定的值(通常是一個對象形式傳遞的參數(shù)),如果沒有傳遞值,則默認(rèn)為一個空對象,將其賦值給 params
變量。然后,從 params
對象中解構(gòu)出 unit
和 append
參數(shù),并分別設(shè)置了默認(rèn)值為空字符串。這里的 unit
和 append
參數(shù)的含義與前面提到的 numberToChineseWords
函數(shù)中的對應(yīng)參數(shù)一致,用于自定義中文大寫金額中整數(shù)部分的單位以及整數(shù)金額后的追加字符。
(2)獲取原始文本內(nèi)容與初始轉(zhuǎn)換
接著,獲取元素的原始文本內(nèi)容 originVal
,這個值用于后續(xù)在元素獲取焦點(diǎn)時還原用戶看到的原始數(shù)字金額,方便編輯。如果元素有 innerHTML
(即元素內(nèi)部包含文本內(nèi)容),則直接調(diào)用前面定義的 numberToChineseWords
函數(shù),將元素的 innerText
(也就是當(dāng)前顯示的文本內(nèi)容,這里假設(shè)是數(shù)字金額相關(guān))按照傳入的 unit
和 append
參數(shù)進(jìn)行轉(zhuǎn)換,將轉(zhuǎn)換后的中文大寫金額結(jié)果重新賦值給元素的 innerHTML
,實(shí)現(xiàn)了初始加載時將數(shù)字金額轉(zhuǎn)換為中文大寫金額顯示的功能。
(3)焦點(diǎn)事件處理
添加 focus
事件監(jiān)聽器,當(dāng)元素獲得焦點(diǎn)時,在對應(yīng)的事件處理函數(shù)中,將事件目標(biāo)(也就是當(dāng)前元素)的 value
屬性設(shè)置為之前保存的 originVal
,這樣用戶在點(diǎn)擊輸入框等操作使元素獲得焦點(diǎn)時,能夠看到原始的數(shù)字金額內(nèi)容,便于進(jìn)行修改編輯,保證了用戶交互體驗(yàn)的連貫性和便捷性。
(4)失焦事件處理
添加 blur
事件監(jiān)聽器,當(dāng)元素失去焦點(diǎn)時,在事件處理函數(shù)中,首先獲取當(dāng)前元素的 value
屬性值(也就是用戶編輯后的值),將其賦值給 originVal
,以便后續(xù)再次操作時能基于最新的值進(jìn)行還原等處理。然后,再次調(diào)用 numberToChineseWords
函數(shù),將編輯后的 value
按照 unit
和 append
參數(shù)進(jìn)行轉(zhuǎn)換,將轉(zhuǎn)換后的中文大寫金額結(jié)果重新賦值給元素的 value
屬性,實(shí)現(xiàn)了用戶編輯完數(shù)字金額后,自動將其轉(zhuǎn)換為中文大寫金額進(jìn)行顯示的功能。
到此這篇關(guān)于vue指令實(shí)現(xiàn)數(shù)字和大寫中文實(shí)時互轉(zhuǎn)的文章就介紹到這了,更多相關(guān)vue數(shù)字和大寫中文互轉(zhuǎn)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解基于vue-cli3.0如何構(gòu)建功能完善的前端架子
這篇文章主要介紹了詳解基于vue-cli3.0如何構(gòu)建功能完善的前端架子,本文整合出具備基礎(chǔ)功能的前端架子,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-10-10Vue之Element級聯(lián)選擇器多選傳值以及回顯方式(樹形結(jié)構(gòu))
這篇文章主要介紹了Vue之Element級聯(lián)選擇器多選傳值以及回顯方式(樹形結(jié)構(gòu)),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-07-07