Vue3實(shí)現(xiàn)進(jìn)制轉(zhuǎn)換器的具體方案
在線工具網(wǎng)址:https://see-tool.com/base-converter
工具截圖:

一、核心設(shè)計(jì)思路
1.1 十進(jìn)制中轉(zhuǎn)策略
所有進(jìn)制轉(zhuǎn)換都通過(guò)十進(jìn)制作為中轉(zhuǎn)站:
任意進(jìn)制 → parseInt(value, base) → 十進(jìn)制 十進(jìn)制 → decimal.toString(base) → 目標(biāo)進(jìn)制
這樣避免了 N×(N-1) 種轉(zhuǎn)換函數(shù)的組合爆炸,復(fù)雜度從 O(n²) 降至 O(n)。
1.2 防死鎖機(jī)制
四個(gè)輸入框?qū)崟r(shí)同步時(shí),必須防止循環(huán)觸發(fā):
let isUpdating = false
const onSyncInput = (source) => {
if (isUpdating) return // 阻止遞歸調(diào)用
isUpdating = true
// ... 執(zhí)行轉(zhuǎn)換邏輯
isUpdating = false
}
二、同步轉(zhuǎn)換模式實(shí)現(xiàn)
2.1 核心轉(zhuǎn)換函數(shù)
const onSyncInput = (source) => {
if (isUpdating) return
isUpdating = true
try {
let decimalNum = 0
let cleanValue = ''
// 第一步: 數(shù)據(jù)清洗 + 轉(zhuǎn)十進(jìn)制
switch (source) {
case 'binary':
// 去除空格、下劃線、0b前綴
cleanValue = binaryValue.value.replace(/[\s_]/g, '').replace(/^0[bB]/, '')
// 正則驗(yàn)證是否為合法二進(jìn)制
if (cleanValue && /^[01]+$/.test(cleanValue)) {
decimalNum = parseInt(cleanValue, 2)
} else {
clearOthers('binary') // 清空其他框
isUpdating = false
return
}
break
case 'octal':
cleanValue = octalValue.value.replace(/[\s_]/g, '').replace(/^0[oO]/, '')
if (cleanValue && /^[0-7]+$/.test(cleanValue)) {
decimalNum = parseInt(cleanValue, 8)
} else {
clearOthers('octal')
isUpdating = false
return
}
break
case 'decimal':
cleanValue = decimalValue.value.replace(/[\s_,]/g, '')
if (cleanValue && /^\d+$/.test(cleanValue)) {
decimalNum = parseInt(cleanValue, 10)
} else {
clearOthers('decimal')
isUpdating = false
return
}
break
case 'hex':
cleanValue = hexValue.value.replace(/[\s_]/g, '').replace(/^0[xX]/, '')
if (cleanValue && /^[0-9A-Fa-f]+$/.test(cleanValue)) {
decimalNum = parseInt(cleanValue, 16)
} else {
clearOthers('hex')
isUpdating = false
return
}
break
}
// 第二步: 廣播更新其他進(jìn)制(跳過(guò)源輸入框)
if (source !== 'binary') {
binaryValue.value = formatValue(decimalNum.toString(2), 2)
}
if (source !== 'octal') {
octalValue.value = formatValue(decimalNum.toString(8), 8)
}
if (source !== 'decimal') {
decimalValue.value = decimalNum.toString()
}
if (source !== 'hex') {
let hex = decimalNum.toString(16)
if (uppercaseHex.value) hex = hex.toUpperCase()
hexValue.value = formatValue(hex, 16)
}
} catch (err) {
console.error('Conversion error:', err)
}
isUpdating = false
}
關(guān)鍵點(diǎn):
- 數(shù)據(jù)清洗: 用正則去除空格、下劃線、前綴等干擾字符
- 嚴(yán)格驗(yàn)證: 每種進(jìn)制都有對(duì)應(yīng)的正則驗(yàn)證規(guī)則
- 跳過(guò)源框: 避免回填源輸入框?qū)е鹿鈽?biāo)跳動(dòng)
- 異常處理: try-catch 防止非法輸入崩潰
2.2 數(shù)據(jù)驗(yàn)證正則
/^[01]+$/ // 二進(jìn)制: 只允許 0 和 1 /^[0-7]+$/ // 八進(jìn)制: 只允許 0-7 /^\d+$/ // 十進(jìn)制: 只允許數(shù)字 /^[0-9A-Fa-f]+$/ // 十六進(jìn)制: 允許 0-9 和 A-F(大小寫)
2.3 格式化顯示函數(shù)
const formatValue = (value, base) => {
let formatted = value
// 1. 添加前綴(可選)
let prefix = ''
if (showPrefix.value) {
switch (base) {
case 2: prefix = '0b'; break
case 8: prefix = '0o'; break
case 16: prefix = '0x'; break
}
}
// 2. 數(shù)字分組(提升可讀性)
if (digitGrouping.value && formatted.length > 4) {
let groupSize = 4
if (base === 2) groupSize = 4 // 二進(jìn)制: 1010 1100
else if (base === 8) groupSize = 3 // 八進(jìn)制: 123 456
else if (base === 10) groupSize = 3 // 十進(jìn)制: 123 456
else if (base === 16) groupSize = 4 // 十六進(jìn)制: 1A2B 3C4D
// 從右向左分組
const groups = []
for (let i = formatted.length; i > 0; i -= groupSize) {
groups.unshift(formatted.substring(Math.max(0, i - groupSize), i))
}
formatted = groups.join(' ')
}
return prefix + formatted
}
分組規(guī)則:
- 二進(jìn)制/十六進(jìn)制: 每 4 位一組
- 八進(jìn)制/十進(jìn)制: 每 3 位一組
2.4 輔助函數(shù)
// 清除其他輸入框
const clearOthers = (except) => {
if (except !== 'binary') binaryValue.value = ''
if (except !== 'octal') octalValue.value = ''
if (except !== 'decimal') decimalValue.value = ''
if (except !== 'hex') hexValue.value = ''
}
// 清除全部
const clearAll = () => {
binaryValue.value = ''
octalValue.value = ''
decimalValue.value = ''
hexValue.value = ''
}
// 復(fù)制文本(去除格式化空格)
const copyText = async (text) => {
if (!text) return
try {
// 去除空格、下劃線、前綴,復(fù)制純凈數(shù)據(jù)
const cleanText = text.replace(/[\s_]/g, '')
await navigator.clipboard.writeText(cleanText)
safeMessage.success(t('baseConverter.notifications.copySuccess'))
} catch (err) {
console.error('Failed to copy:', err)
safeMessage.error(t('baseConverter.notifications.copyFailed'))
}
}
三、自定義進(jìn)制模式實(shí)現(xiàn)
3.1 核心轉(zhuǎn)換函數(shù)
const convertCustom = () => {
if (!customInput.value.trim()) {
customOutput.value = ''
return
}
try {
// 利用原生 API 支持 2-36 進(jìn)制
const decimal = parseInt(customInput.value, customFromBase.value)
if (isNaN(decimal)) {
customOutput.value = t('common.invalidInput')
return
}
customOutput.value = decimal.toString(customToBase.value).toUpperCase()
} catch (err) {
customOutput.value = t('common.conversionError')
}
}
原生 API 優(yōu)勢(shì):
parseInt(str, radix): 支持 2-36 進(jìn)制解析num.toString(radix): 支持 2-36 進(jìn)制輸出- 無(wú)需自己實(shí)現(xiàn)進(jìn)制轉(zhuǎn)換算法
3.2 進(jìn)制交換函數(shù)
const swapBases = () => {
// 交換源進(jìn)制和目標(biāo)進(jìn)制
const temp = customFromBase.value
customFromBase.value = customToBase.value
customToBase.value = temp
// 將輸出作為新的輸入
customInput.value = customOutput.value
convertCustom()
}
四、響應(yīng)式配置實(shí)現(xiàn)
4.1 大小寫切換
watch(uppercaseHex, () => {
if (hexValue.value) {
hexValue.value = uppercaseHex.value
? hexValue.value.toUpperCase()
: hexValue.value.toLowerCase()
}
})
4.2 前綴/分組切換
// 監(jiān)聽(tīng)前綴切換
watch(showPrefix, () => {
if (decimalValue.value) {
onSyncInput('decimal') // 重新格式化所有輸入框
}
})
// 監(jiān)聽(tīng)數(shù)字分組切換
watch(digitGrouping, () => {
if (decimalValue.value) {
onSyncInput('decimal')
}
})
4.3 自定義進(jìn)制變化
// 監(jiān)聽(tīng)自定義進(jìn)制變化,自動(dòng)重新轉(zhuǎn)換
watch([customFromBase, customToBase], () => {
convertCustom()
})
五、狀態(tài)管理
5.1 響應(yīng)式狀態(tài)定義
// Tab 切換
const activeTab = ref('sync')
// 同步轉(zhuǎn)換模式的四個(gè)輸入框
const binaryValue = ref('')
const octalValue = ref('')
const decimalValue = ref('')
const hexValue = ref('')
// 配置選項(xiàng)
const uppercaseHex = ref(false) // 十六進(jìn)制大寫
const showPrefix = ref(false) // 顯示前綴 (0x, 0b)
const digitGrouping = ref(true) // 數(shù)字分組
// 自定義進(jìn)制模式
const customFromBase = ref(10) // 源進(jìn)制
const customToBase = ref(16) // 目標(biāo)進(jìn)制
const customInput = ref('') // 輸入值
const customOutput = ref('') // 輸出值
// 防死鎖標(biāo)志位
let isUpdating = false
六、已知限制與改進(jìn)方向
6.1 大數(shù)精度問(wèn)題
當(dāng)前使用 Number 類型,超過(guò) Number.MAX_SAFE_INTEGER (2^53 - 1) 會(huì)丟失精度。
改進(jìn)方案:
// 使用 BigInt 替代 Number
const decimalNum = BigInt(`0b${cleanValue}`)
const result = decimalNum.toString(16)
注意事項(xiàng):
BigInt不支持小數(shù)BigInt和Number不能直接運(yùn)算- 需要特殊處理邊界情況
6.2 性能優(yōu)化
對(duì)于頻繁輸入場(chǎng)景,可添加防抖:
import { debounce } from 'lodash-es'
const onSyncInput = debounce((source) => {
// ... 轉(zhuǎn)換邏輯
}, 100)
七、核心流程總結(jié)
用戶輸入 → 數(shù)據(jù)清洗 → 正則驗(yàn)證 → parseInt(轉(zhuǎn)十進(jìn)制)
↓
十進(jìn)制中轉(zhuǎn)
↓
格式化顯示 ← toString(轉(zhuǎn)目標(biāo)進(jìn)制) ← 廣播更新
核心原則:
- 十進(jìn)制中轉(zhuǎn): 避免組合爆炸
- 防死鎖機(jī)制: 阻止循環(huán)觸發(fā)
- 數(shù)據(jù)清洗: 確保輸入合法
- 格式化顯示: 提升可讀性
- 原生 API: 避免重復(fù)造輪子
以上就是Vue3實(shí)現(xiàn)進(jìn)制轉(zhuǎn)換器的具體方案的詳細(xì)內(nèi)容,更多關(guān)于Vue3進(jìn)制轉(zhuǎn)換器的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Vue文件如何轉(zhuǎn)換成base64并去除多余的文件類型前綴
這篇文章主要介紹了Vue文件如何轉(zhuǎn)換成base64并去除多余的文件類型前綴問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03
Vue簡(jiǎn)明介紹配置對(duì)象的配置選項(xiàng)
我們知道每一個(gè)vue項(xiàng)目應(yīng)用都是通過(guò)vue的構(gòu)造函數(shù)進(jìn)行創(chuàng)建一個(gè)新的vue項(xiàng)目的。創(chuàng)建vue實(shí)例的配置對(duì)象,可以包括一下屬性選項(xiàng),比如:data、methods、watch、template等等,每一個(gè)選項(xiàng)都有不同的功能,大家可以根據(jù)自己的需求選擇不同的配置2022-08-08
vue輸入框中輸完后光標(biāo)自動(dòng)跳到下一個(gè)輸入框中的實(shí)現(xiàn)方法
最近在工作中遇到了些問(wèn)題,總結(jié)下分享給同樣遇到這個(gè)問(wèn)題的朋友,這篇文章主要給大家介紹了關(guān)于vue輸入框中輸完后光標(biāo)自動(dòng)跳到下一個(gè)輸入框中的實(shí)現(xiàn)方法,需要的朋友可以參考下2023-03-03
解決elementui上傳組件el-upload無(wú)法第二次上傳問(wèn)題
這篇文章主要介紹了解決elementui上傳組件el-upload無(wú)法第二次上傳問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03
使用el-upload實(shí)現(xiàn)文件上傳方式(包括預(yù)覽,下載)
該文章介紹了兩種文件上傳、預(yù)覽和下載的方法,分別是通過(guò)卡片形式和按鈕形式,卡片形式中的下載和預(yù)覽功能尚未完善,父組件使用了el-upload組件,可以實(shí)現(xiàn)新增、編輯和查看文件的功能2025-11-11
Vue.js bootstrap前端實(shí)現(xiàn)分頁(yè)和排序
這篇文章主要為大家詳細(xì)介紹了Vue.js結(jié)合bootstrap前端實(shí)現(xiàn)分頁(yè)和排序效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03
Vue3使用v-if指令進(jìn)行條件渲染的實(shí)例代碼
條件渲染是根據(jù)條件的真假來(lái)有條件地渲染元素,在Vue.js 3.x中,常見(jiàn)的條件渲染包括使用v-if指令和v-show指令,本文講解使用v-if指令進(jìn)行條件渲染,需要的朋友可以參考下2024-03-03
關(guān)于element-ui中@selection-change執(zhí)行兩次的問(wèn)題
這篇文章主要介紹了關(guān)于element-ui中@selection-change執(zhí)行兩次的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08

