一、開發背景
-
產品出設計稿要求做一個仿原生app短信驗證碼組件,花了兩小時搞出來一個還可以的組件,支持螢屏自適應,可以用于彈出框,或自己封裝的vue組件里,希望可以幫助那些被產品壓榨的同學,哈哈,??
-
其核心思想就是利用一個輸入框使用css3,translate屬性,每輸入一次后向右位移一個單位位置,直到輸入完驗證碼個數消失,然后定義一個陣列smsCodeList,初始化時push物件
smsCodeList = [{
val: '',
isError: ''
}]
二、費發不多說,先看演示
演示


三、代碼解釋
// html代碼
<div class='sms-check-code-wrapper' @click='handleClick'>
<div >
<div :
:style="{'color': error ? errorColor : errorColorDefault}">
{{ title }}</div>
<div class='sms-code-box'>
<div :style="{'transform': `translate(${inputBoxActive}%)`}">
<input
ref='refInout'
v-show='isShowInputBox'
type='number'
v-model='inputValue'
class='sms-code-input'
:style="{
'width': style.smsCodeItemWidth + '%',
'paddingLeft': style.inputPL + '%'
}"
@keyup="onKeyUp"
@keydown='onKeyDown'
v-focus
:maxlength='codeNum'
autocomplete="one-time-code"
inputmode="numeric"
value=''
/>
</div>
<div class='sms-code-bottom flex-sb'>
<div class='sms-code-item'
:style="{
'width': style.smsCodeItemWidth + '%'
}"
v-for='(item, index) in smsCodeList' :key='index'>
<span :
:style="{'color': item.isError ? errorColor : errorColorDefault}">
{{ item.val }}</span>
<span :
:style="{'backgroundColor': item.isError ? errorColor : errorColorDefault}">
</span>
</div>
</div>
</div>
</div>
</div>
只需簡單的這幾行html結構,用來渲染標題和輸入框和驗證碼組件
js 代碼也很簡單
// 首先定義一些初始默認值,因為默認按照6位數驗證碼來的
let defaultCodeNum = 6
let defaultMoveUnit = 17.2
let defaultInputPL = 7
let defaultSmsCodeItemWidth = 14
export default {
name: "VueSmsCheckCode",
directives: {
focus: {
inserted: function (el) {
el.focus()
}
}
},
props: {
title: {
type: String,
default: '請錄入驗證碼'
},
codeNum: { // 驗證碼個數
type: Number,
default: 6
},
isError: { // 驗證碼錯誤顯示錯誤提示
type: Boolean,
default: false
},
errorColor: {
type: String,
default: '#D81A1A'
}
},
data() {
return {
smsCodeList: [], // 驗證碼輸入顯示在div上的數字
inputValue: '', // 輸入框的值
smsValue: '', // 驗證碼完畢后歸總的變數
moveUnit: 17.2, // input 位移單位
inputBoxActive: 0, // 當前輸入框位移位置
currentIndex: 0, // 當前驗證碼索引
isShowInputBox: true, // 是否顯示輸入框
error: false, // 驗證碼錯誤報紅
errorColorDefault: '#b1b1b1', // 默認錯誤輸入框顏色
style: { // 默認樣式
inputPL: 0, // input padding-left值
smsCodeItemWidth: 0, // 驗證碼顯示item的寬度(自適應)
}
}
},
created() {
this.reDomRender() // 初始化時,通過傳過來的驗證碼個數重新渲染組件(各個dom位置,寬度等重新計算)
this.compareList() // push 默認資料
this.inputPaving() // 當點擊手機驗證碼自動填充時,自動平鋪資料
},
methods: {
reDomRender() {
this.style = {
inputPL: Math.round(defaultCodeNum / (this.codeNum / defaultInputPL)),
smsCodeItemWidth: Math.round(defaultCodeNum / this.codeNum * defaultSmsCodeItemWidth)
}
this.moveUnit = Math.round(defaultCodeNum / (this.codeNum / (defaultMoveUnit - .3333)))
},
compareList() {
for (let i = 0; i < this.codeNum; i++) {
if (this.smsCodeList.length < this.codeNum) {
this.smsCodeList.push({
val: '',
isError: this.isError
})
}
}
},
initAll() {
this.smsCodeList = []
this.compareList()
this.inputValuehttps://www.cnblogs.com/snail-boy/archive/2022/05/31/= ''
this.smsValuehttps://www.cnblogs.com/snail-boy/archive/2022/05/31/= ''
this.inputBoxActive = 0
this.currentIndex = 0
this.isShowInputBox = true
// 延時解決游標聚焦
setTimeout(() => {
this.$refs.refInout.focus()
})
},
// 當點擊驗證碼時,inputBoxActive,值要分鋪在每個輸入框里
inputPaving() {
let v = this.inputValue
if (v.length > 0) {
v.split('').forEach((item, index) => {
if (index <= v.length) {
this.smsCodeList[index].val = item
const inputPosition = (index + 1) * this.moveUnit
this.inputBoxActive = inputPosition >= 100 ? 100 : inputPosition
this.currentIndex = index + 1
this.smsValue += item
this.inputValuehttps://www.cnblogs.com/snail-boy/archive/2022/05/31/= ''
if (index + 1 === this.codeNum) {
this.isShowInputBox = false
this.sendFun()
}
}
})
}
},
onKeyDown(e) {
let key = e.key;
e.returnValue = https://www.cnblogs.com/snail-boy/archive/2022/05/31/!(key ==='e' || key === 'E' || key === '+' || key === '-');
},
onKeyUp(e) {
if (this.currentIndex < 1) return
if (e.code === 'Backspace' || e.key === 'Backspace') { // 會退
this.currentIndex = this.currentIndex - 1
this.inputBoxActive = this.inputBoxActive - this.moveUnit
this.smsCodeList = this.smsCodeList.map((val, index) => {
if (index === this.currentIndex) {
val.val = ''
val.isError = this.isError
return val
}
return val
})
}
},
handleClick() {
this.$refs.refInout.focus()
},
sendFun() {
this.$emit('finish', this.smsValue)
}
},
watch: {
inputValue(v) { // 監聽輸入框輸入的值
if (!v) return
// 初始化時,點擊軟鍵盤上的驗證碼自動填充時分鋪input資料
if (v.length > 1) {
this.inputPaving()
return;
}
this.inputBoxActive = this.inputBoxActive + this.moveUnit
this.smsCodeList.map((val, index) => {
if (this.currentIndex === index) {
if(val) {
//當前輸入的位置使紅色底部條初始化
val.isError = false
}
val.val = v
return val
}
return val
})
this.currentIndex += 1
this.inputValuehttps://www.cnblogs.com/snail-boy/archive/2022/05/31/= ''
if (this.currentIndex >= this.codeNum) { // 當最后一位時發
this.isShowInputBox = false
this.smsCodeList.forEach(val => {
this.smsValue += val.val
})
this.sendFun()
}
},
isError(v) { // 監聽驗證碼是否錯誤
this.error = v
if (v) {
this.smsCodeList.map(value =https://www.cnblogs.com/snail-boy/archive/2022/05/31/> {
value.isError = true
return value
})
this.initAll()
}
}
}
}
剩下的就是css了
npm install vue-sms-check-code --save
最新版1.0.1 (2022/5/25)
包常規操作下載使用
另外需要完整的代碼請到github或gitee上下載
開源并總結整理真的很費時間,如果不錯還請star
???問題請issues
gitee原始碼地址
github原始碼地址
原始碼里有example 使用方式,使用灰常簡單,
開源并總結整理真的很費時間,歡迎star
底部測驗22
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/483948.html
標籤:.NET技术
