vue实现自定义身份证,数字键盘(光标,输入框,键盘)
组件介绍
vue实现自定义身份证键盘(光标,输入框,键盘全手写)
组件代码
<template>
<div
class="myKeyboard"
@click.stop="handleFocus"
@blur="handleBlur"
tabindex="0"
>
<div class="input-container">
<div class="input-top">
<div class="input-label" :style="labelStyle" :class="labelClass">
{{ inputLabel }}
</div>
<div
class="inputText"
id="inputText"
:style="inputStyle"
:class="inputClass"
>
<span class="cursor">
<span class="holder showWhite">|</span>
</span>
<span class="place-holder">{{ placeHolder }}</span>
<span
class="right-space"
:style="{ color: zcolor }"
@click="moveCursor"
>占位</span
>
<span class="right-btn">
<!-- <span v-if="clearShow" class="clear" @click="handleClear"> -->
<img
v-if="clearShow"
class="clear"
@click="handleClear"
src="@/assets/keyboard/keyboard_clear.png"
alt=""
/>
<slot></slot>
</span>
</div>
</div>
<div class="error" :style="errorStyle" v-if="errorShow">
{{ errorMessage }}
</div>
<div class="errorSpace" v-else></div>
</div>
<div class="number hidden" :class="numberClass" :style="numberStyle">
<div class="mybtn" @click.stop="handleBlur">
<img src="@/assets/keyboard/keyboard_down.png" alt="" />
</div>
<div class="mynum">
<div class="num" @click="handleNum('1')">1</div>
<div class="num" @click="handleNum('2')">2</div>
<div class="num" @click="handleNum('3')">3</div>
<div class="num" @click="handleNum('4')">4</div>
<div class="num" @click="handleNum('5')">5</div>
<div class="num" @click="handleNum('6')">6</div>
<div class="num" @click="handleNum('7')">7</div>
<div class="num" @click="handleNum('8')">8</div>
<div class="num" @click="handleNum('9')">9</div>
<div v-if="keyboard == 'card'" class="num" @click="handleNum('X')">
X
</div>
<div v-if="keyboard == 'tel'" class="num" @click="handleNum('0')">
0
</div>
<div class="num" @click="handleNum('0')">0</div>
<div
class="num"
@click.stop="handleDelete"
@touchstart="gtouchstart"
@touchend="gtouchend"
@touchmove="gtouchmove"
>
<img src="@/assets/keyboard/keyboard_del1.png" alt="" />
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
indexNum: {
type: Number,
default: 0,
},
numberDis: {
type: Boolean,
default: false,
},
required: {
type: Boolean,
default: false,
},
keyboard: {
type: String,
default: 'card',
},
oldValue: {
type: String,
default: '',
},
zcolor: {
type: String,
default: '#fff',
},
inputLabel: {
type: String,
default: '',
},
placeHolder: {
type: String,
default: '请输入',
},
errorMessage: {
type: String,
default: '请输入正确的信息',
},
errorShow: {
type: Boolean,
default: false,
},
errorStyle: {
type: Object,
default: function () {
return {}
},
},
clearShow: {
type: Boolean,
default: false,
},
labelClass: {
type: String,
default: '',
},
labelStyle: {
type: Object,
default: function () {
return {}
},
},
inputClass: {
type: String,
default: '',
},
inputStyle: {
type: Object,
default: function () {
return {}
},
},
numberClass: {
type: String,
default: '',
},
numberStyle: {
type: Object,
default: function () {
return {}
},
},
},
data() {
return {
inputArea: '',
stop: false,
clickNum: false,
show: false,
value: '',
inputValue: '',
}
},
watch: {
oldValue(val) {
if (val != this.inputValue) {
this.handleClear()
this.handleOld()
}
},
required(val) {
this.handleRequired(val)
},
},
created() {
this.$toast.clear()
},
mounted() {
this.handleRequired(this.required)
this.handleOld()
},
methods: {
handleRequired(val) {
const inputLabel =
document.getElementsByClassName('input-label')[this.indexNum]
if (val) {
inputLabel.className = 'input-label required'
} else {
inputLabel.className = 'input-label'
}
},
handleOld() {
if (this.oldValue != '') {
for (const item of this.oldValue) {
const span = document.createElement('span')
span.className = 'val'
span.innerText = item
const space = document.createElement('span')
space.className = 'space'
space.innerText = ''
span.addEventListener('click', this.moveCursor)
const cursor =
document.getElementsByClassName('cursor')[this.indexNum]
const inputArea =
document.getElementsByClassName('inputText')[this.indexNum]
inputArea.insertBefore(space, cursor)
inputArea.insertBefore(span, cursor)
}
}
const placeHolder =
document.getElementsByClassName('place-holder')[this.indexNum]
if (this.oldValue == '') {
placeHolder.className = 'place-holder'
} else {
placeHolder.className = 'place-holder hidden'
}
this.inputValue = this.oldValue
this.$emit('keyboard-input', this.inputValue)
},
handleFocus(event) {
if (!this.numberDis) {
this.$emit('indexNum', this.indexNum)
const number = document.getElementsByClassName('number')[this.indexNum]
number.className = 'number'
this.setCursorFlash()
this.handleValue()
}
},
handleNum(value) {
const number = document.getElementsByClassName('number')[this.indexNum]
number.className = 'number'
const span = document.createElement('span')
span.className = 'val'
span.innerText = value
const space = document.createElement('span')
space.className = 'space'
space.innerText = ''
span.addEventListener('click', this.moveCursor)
const cursor = document.getElementsByClassName('cursor')[this.indexNum]
const inputArea =
document.getElementsByClassName('inputText')[this.indexNum]
inputArea.insertBefore(space, cursor)
inputArea.insertBefore(span, cursor)
this.handleValue()
},
handleBlur(e) {
clearInterval(this.intervalId)
const placeHolder =
document.getElementsByClassName('holder')[this.indexNum]
placeHolder.className = 'holder showWhite'
const number = document.getElementsByClassName('number')[this.indexNum]
number.className = 'number hidden'
const inputText =
document.getElementsByClassName('inputText')[this.indexNum]
inputText.className = 'inputText'
this.handleValue()
const inputArea =
document.getElementsByClassName('inputText')[this.indexNum]
const reset =
document.getElementsByClassName('place-holder')[this.indexNum]
const cursor = document.getElementsByClassName('cursor')[this.indexNum]
const ele = inputArea.replaceChild(reset.previousSibling, cursor)
inputArea.insertBefore(ele, reset)
},
moveCursor(event) {
const inputArea =
document.getElementsByClassName('inputText')[this.indexNum]
const cursor = document.getElementsByClassName('cursor')[this.indexNum]
if (event.currentTarget.className == 'right-space') {
const ele = inputArea.replaceChild(
event.currentTarget.previousSibling.previousSibling,
cursor,
)
inputArea.insertBefore(ele, event.currentTarget.previousSibling)
} else {
const tempEle = event.currentTarget
const nodeName = event.currentTarget.nextSibling.nodeName
const temp = event.currentTarget.previousSibling
const ele = inputArea.replaceChild(temp, cursor)
inputArea.insertBefore(ele, event.currentTarget)
}
},
handleDelete() {
const inputArea =
document.getElementsByClassName('inputText')[this.indexNum]
const cursor = document.getElementsByClassName('cursor')[this.indexNum]
let n = 2
while (cursor.previousSibling && n > 0) {
inputArea.removeChild(cursor.previousSibling)
n--
}
this.handleValue()
},
gtouchstart(e) {
this.timeOutEvent = setTimeout(() => {
this.longPress()
}, 500)
return false
},
gtouchend() {
clearTimeout(this.timeOutEvent)
clearInterval(this.press)
if (this.timeOutEvent != 0) {
}
return false
},
gtouchmove() {
clearTimeout(this.timeOutEvent)
clearInterval(this.press)
this.timeOutEvent = 0
},
longPress() {
this.timeOutEvent = 0
this.press = setInterval(() => {
this.handleDelete()
}, 300)
},
setCursorFlash() {
const placeHolder =
document.getElementsByClassName('holder')[this.indexNum]
let isShowCursor = false
if (this.intervalId) {
clearInterval(this.intervalId)
}
this.intervalId = setInterval(function () {
isShowCursor = !isShowCursor
if (isShowCursor) {
placeHolder.className = 'holder'
} else {
placeHolder.className = 'holder showWhite'
}
}, 500)
},
handleClear() {
const father = document.getElementsByClassName('inputText')[this.indexNum]
const child =
document.getElementsByClassName('inputText')[this.indexNum].childNodes
for (let i = child.length - 1; i >= 0; i--) {
if (child[i].className == 'val' || child[i].className == 'space') {
father.removeChild(child[i])
}
}
},
handleValue() {
const val = document
.getElementsByClassName('inputText')
[this.indexNum].querySelectorAll('.val')
const arr = []
arr[this.indexNum] = []
for (let i = 0; i < val.length; i++) {
arr[this.indexNum].push(val[i].innerHTML)
}
this.inputValue = arr[this.indexNum].toString()
this.inputValue = this.inputValue.split(',').join('')
this.$emit('keyboard-input', this.inputValue)
const placeHolder =
document.getElementsByClassName('place-holder')[this.indexNum]
if (this.inputValue == '') {
placeHolder.className = 'place-holder'
} else {
placeHolder.className = 'place-holder hidden'
}
},
},
}
</script>
<style scoped lang="less">
.myKeyboard:focus {
outline: none;
}
.input-container {
display: flex;
flex-direction: column;
box-sizing: border-box;
padding: 1rem;
padding-bottom: 0.2rem;
width: 100%;
border-bottom: 1px solid #eee;
background: #fff;
font-size: 1.04rem;
.acitve {
border: 1px solid #2e8fff !important;
}
.input-top {
display: flex;
align-items: center;
box-sizing: border-box;
width: 100%;
}
.error {
color: #ee0a24;
font-size: 0.75rem;
}
.errorSpace {
width: 1rem;
height: 1.2rem;
}
.required::before {
position: absolute;
left: 0.5rem;
color: #ee0a24;
content: '*';
font-size: 0.875rem;
}
.inputText {
position: relative;
flex: 1;
width: 80%;
border: none;
}
.right-btn {
position: absolute;
right: 2%;
.clear {
width: 1.5rem;
}
:nth-child(2) {
}
}
.right-space {
}
.place-holder {
color: #c8c8c8;
}
}
.number {
position: fixed;
bottom: 0;
z-index: 999999;
padding-bottom: 2%;
width: 100%;
background-color: #f0f0f0;
font-size: 2rem;
.mybtn {
height: 2rem;
text-align: center;
line-height: 2rem;
img {
height: 100%;
}
}
.mynum {
display: flex;
flex-wrap: wrap;
height: calc(100% - 2rem);
.num {
display: flex;
align-items: center;
flex: 1 0 30%;
justify-content: center;
height: 3.4rem;
border-top: 1px solid #eee;
border-left: 1px solid #eee;
background-color: #fff;
text-align: center;
&:active {
background-color: rgb(202, 202, 202);
}
img {
pointer-events: none;
}
}
}
}
.hidden {
display: none;
}
.showWhite {
color: #fff;
}
</style>
效果图
组件使用
引用
和正常引用组件的操作相同
import number from '文件地址'
export default {
components:{
number
},
data() {
return {
indexNum: 0,
oldValue: ''
}
},
methods:{
handleKeyBoard(value) {
console.log(value)
this.oldValue = value
},
}
}
使用
<number
:index-num="indexNum"
@keyboard-input="handleKeyBoard"
:old-value="oldValue"
>
</number>
参数介绍
参数 |
说明 |
indexNum |
输入框索引(必填字段),Number,默认0 |
oldValue |
父组件传的输入框值(必填字段),String |
keyboard |
键盘类型,String,(card:身份证,tel:数字)默认card |
zcolor |
占位符颜色(建议设置和输入框背景同色),String,默认#fff |
inputLabel |
label文字,String |
placeHolder |
当输入框内无文字时显示,String,默认请输入 |
errorMessage |
错误提示信息,String,默认请输入正确的信息 |
errorShow |
是否显示错误提示信息,Boolean,默认false |
errorStyle |
错误提示信息样式,Object |
clearShow |
是否显示清除键,Boolean,默认false |
labelClass |
label动态类名,String |
labelStyle |
label样式,Object |
inputClass |
输入框动态类名,String |
inputStyle |
输入框样式,Object |
numberClass |
键盘类名,String |
numberStyle |
键盘样式,Object |
numberDis |
是否聚焦,Boolean |
required |
是否必填,(true:出现红星,false:不出现),Boolean |
方法
事件 |
说明 |
keyboard-input |
输入框输入事件,回调参数为输入框内输入的值,每次改变值均调用 |
插槽
标签 |
说明 |
slot |
组件内已预留插槽,可根据自己的需要在输入框内添加自己的标签 |