前言:uniapp 在做需求的时候,经常会遇到;验证码输入框 或者 密码输框 自定义样式输入框 或者 格式化显示 银行卡 手机号码等等:这里总结了两种 常用的实现方式;
从这两种实现方式 其实也能延伸出其他的显示 方式;
先看样式: 自己实现 光标闪烁动画
第一种:可以识别 获得焦点 失去焦点
第一种实现的思路:
实际上就是,下层的真实 input 负责响应系统的输入,上面一层负责显示
应为输入框在手机端会 出现长按 学着 复制等等 输入框自带属性:这里的处理思路是: 拉长输入框,延伸到屏幕以外; 这样就不会出现 系统出现的一些选项,但是有时候 还会有个别情况!(可能性很低)
position: absolute; color: #8cff21; background-color: rgba($color: #ff1702, $alpha: 0.2); left: -150%; height: 100%; width: 300%;
这里其实可以延伸出 其他的个性化显示方式比如: 银行卡号 中间带空格这种
第二种: 完全撇开 input, 自己实现输入 软键盘
完整代码:
- uniapp 方向;
- 依赖官方 uni-popup
工程下载https://download.csdn.net/download/nicepainkiller/85214409
<template>
<view class="content">
<view class="title-input-1">
方式1:{
{inputFocus1}}
</view>
<view class="input-box-1">
<input type="number" :focus="inputFocus1" value="" v-model="inputText1" class="input-number" @input="onInput1"
@focus="onFocus1" @blur="onBlur1" maxlength="4" />
<view class="number-box">
<view class="number-item" v-for="(item,index) in inputText1Cache1" :key="index">
<view class="item-number" v-if="item">
{
{item}}
</view>
<view class="item-focus" v-else-if="inputFocus1&&onShowFocus1(index)">
</view>
</view>
</view>
</view>
<view class="title-input-2">
方式2:
</view>
<view class="input-box-2">
<!-- <input type="number" value="" v-model="inputText2" class="input-number" @input="onInput2" @focus="onFocus2"
@blur="onBlur2" maxlength="4" /> -->
<view class="number-box" @click="onOpenInput2()">
<view class="number-item" v-for="(item,index) in inputText2Cache1" :key="index">
<view class="item-number" v-if="item">
{
{item}}
</view>
<view class="item-focus" v-else-if="inputFocus2&&onShowFocus2(index)">
</view>
</view>
</view>
</view>
<uni-popup ref="uniPopup" type="bottom" mask-background-color="rgba(0,0,0,0.0)" @maskClick="onMask">
<view class="number-content">
<view class="content-top">
<view class="number-item" v-for="(item,index) in softNumbers" :key="index" @click="inputNumber(item)">
{
{item}}
</view>
</view>
<view class="content-bottom">
<view class="number-item" v-for="(item,index) in softNumbersBottom" :key="index" @click="inputDele(index)">
{
{item}}
</view>
</view>
</view>
</uni-popup>
</view>
</template>
<script>
export default {
data() {
return {
inputText1: '',
inputFocus1: false,
inputText1Cache1: [, , , , ],
inputText2: '',
inputFocus2: false,
inputText2Cache1: [, , , , ]
}
},
onLoad() {
},
computed: {
softNumbers() {
return ['1', '2', '3', '4', '5', '6', '7', '8', '9']
},
softNumbersBottom() {
return ['', '0', '←']
}
},
methods: {
onShowFocus1(index) {
if (index < this.inputText1.length + 1) {
return true
} else {
return false
}
},
onInput1(e) {
console.log('e.detail:', e.detail)
this.$nextTick(function() {
this.inputText1Cache1 = [, , , , ]
for (let i = 0; i < this.inputText1.length; i++) {
this.inputText1Cache1[i] = this.inputText1[i]
}
if (this.inputText1.length === 4) {
console.log('输入完成!')
uni.showToast({
icon: "none",
position: 'bottom',
title: `输入完成!:${this.inputText1}`
})
}
})
},
onInput1Fouse() {
this.inputFocus1 = true
},
onFocus1() {
console.log('输入框1得到焦点')
this.inputFocus1 = true
},
onBlur1() {
console.log('输入框1失去焦点')
this.inputFocus1 = false
},
onMask() {
console.log("onMask:")
this.inputFocus2 = false
},
onShowFocus2(index) {
if (index < this.inputText2.length + 1) {
return true
} else {
return false
}
},
maskClick() {
},
onOpenInput2() {
console.log('输入框2得到焦点')
this.inputFocus2 = true
this.$refs.uniPopup.open()
},
inputNumber(item) {
if (this.inputText2.length >= 4) {
this.$refs.uniPopup.close()
return
}
this.inputText2 += item
this.$nextTick(function() {
this.inputText2Cache1 = [, , , , ]
for (let i = 0; i < this.inputText2.length; i++) {
this.inputText2Cache1[i] = this.inputText2[i]
}
if (this.inputText2.length === 4) {
console.log('输入完成!')
this.$refs.uniPopup.close()
uni.showToast({
icon: "none",
position: 'bottom',
title: `输入完成!:${this.inputText2}`
})
}
// console.log("inputText2:", this.inputText2)
// console.log(" this.inputText2Cache1:", this.inputText2Cache1)
})
},
inputDele(index) {
if (index === 1) {
if (this.inputText2.length >= 4) {
this.$refs.uniPopup.close()
return
}
this.inputText2 += '0'
this.inputText2Cache1 = [, , , , ]
for (let i = 0; i < this.inputText2.length; i++) {
this.inputText2Cache1[i] = this.inputText2[i]
}
if (this.inputText2.length === 4) {
this.$refs.uniPopup.close()
//console.log('输入完成!')
uni.showToast({
icon: "none",
position: 'bottom',
title: `输入完成!:${this.inputText2}`
})
}
} else if (index === 2) {
if (this.inputText2.length > 0) {
this.inputText2 = this.inputText2.substr(0, this.inputText2.length - 1)
console.log("this.inputText2:", this.inputText2)
this.inputText2Cache1 = [, , , , ]
for (let i = 0; i < this.inputText2.length; i++) {
this.inputText2Cache1[i] = this.inputText2[i]
}
}
}
}
}
}
</script>
<style lang="scss" scoped>
.content {
.title-input-1 {
padding-left: 24rpx;
margin-top: 50rpx;
}
.input-box-1 {
position: relative;
margin: 0 auto;
background-color: #000000;
width: 95%;
height: 88rpx;
margin-top: 50rpx;
.input-number {
position: absolute;
color: #8cff21;
background-color: rgba($color: #ff1702, $alpha: 0.2);
left: -150%;
height: 100%;
width: 300%;
}
.number-box {
position: absolute;
top: 0;
height: 100%;
width: 100%;
background-color: #007AFF;
pointer-events: none;
display: flex;
flex-direction: row;
justify-content: space-around;
align-items: center;
.number-item {
position: relative;
width: 86rpx;
height: 86rpx;
background-color: #FFFFFF;
border: 1px solid #000000;
line-height: 86rpx;
text-align: center;
pointer-events: none;
.item-number {}
.item-focus {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 2px;
height: 50rpx;
background-color: #0c0b0a;
animation: flicker 1s linear 0s infinite;
}
}
}
}
.title-input-2 {
padding-left: 24rpx;
margin-top: 120rpx;
}
.input-box-2 {
position: relative;
margin: 0 auto;
background-color: #000000;
width: 95%;
height: 88rpx;
margin-top: 50rpx;
.input-number {
color: #FFFFFF;
background-color: rgba($color: #ff1702, $alpha: 0.2);
height: 100%;
width: 100%;
}
.number-box {
position: absolute;
top: 0;
height: 100%;
width: 100%;
background-color: #ffb520;
// pointer-events: none;
display: flex;
flex-direction: row;
justify-content: space-around;
align-items: center;
.number-item {
position: relative;
width: 86rpx;
height: 86rpx;
background-color: #FFFFFF;
border: 1px solid #000000;
line-height: 86rpx;
text-align: center;
.item-number {}
.item-focus {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 2px;
height: 50rpx;
background-color: #0c0b0a;
animation: flicker 1s linear 0s infinite;
}
}
}
}
.number-content {
width: 100%;
height: 400rpx;
background-color: #dddddd;
.content-top {
height: 300rpx;
width: 100%;
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items: center;
// background-color: #18BC37;
justify-content: center;
.number-item {
position: relative;
// background-color: #2979FF;
height: 100rpx;
width: 33%;
color: #333333;
line-height: 100rpx;
text-align: center;
border-bottom: 1px solid #FFFFFF;
}
.number-item:nth-child(3n+2) {
border-left: 1px solid #FFFFFF;
border-right: 1px solid #FFFFFF;
}
}
.content-bottom {
height: 100rpx;
width: 100%;
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items: center;
// background-color: #18BC37;
justify-content: center;
.number-item {
position: relative;
// background-color: #2979FF;
height: 100rpx;
width: 33%;
color: #333333;
line-height: 100rpx;
text-align: center;
}
.number-item:nth-child(3n+2) {
border-left: 1px solid #FFFFFF;
border-right: 1px solid #FFFFFF;
}
}
}
@keyframes flicker {
0% {
background-color: rgba($color: #0c0b0a, $alpha: 1);
}
100% {
background-color: rgba($color: #0c0b0a, $alpha: 0.3);
}
}
}
</style>