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 组件内已预留插槽,可根据自己的需要在输入框内添加自己的标签