vue 实现6位数验证码框
vue
vuejs/vue: 是一个用于构建用户界面的 JavaScript 框架,具有简洁的语法和丰富的组件库,可以用于开发单页面应用程序和多页面应用程序。
项目地址:https://gitcode.com/gh_mirrors/vu/vue
免费下载资源
·
效果图
1.第一种实现方式
使用li元素来模拟输入框的显示,没有别的目的,就只是为了语义化,当然你也可以使用其他任意一个元素来模拟,比如div。使用label标签的好处在于它可以跟input的click事件关联上,一方面实现了语义化解决方案,另一方面也省去了我们通过js来唤起虚拟键盘,隐藏输入框
<template>
<div>
<label for="code">
<ul class="security-code-container">
<li class="field-wrap" :class="{'on':seat==index}" v-for="(item, index) in list" :key="index" @click="onClick(index)">
<i class="char-field">{{value[index] || placeholder}}</i>
</li>
</ul>
</label>
<input ref="input"
class="input-code"
@keyup="keyup($event)"
@keydown="keydown($event)"
v-model="value"
id="code"
type="number"
:maxlength="number"
@touchstart="keyup($event)"
@touchend="keydown($event)"
/>
<div class="clean"><span @click.stop="onClean">清除</span></div>
</div>
</template>
<script>
export default {
name: 'SecurityCode',
props: {
number: {
type: Number,
default: 10
},
placeholder: {
type: String,
default:'-'
}
},
data() {
return {
value:'',
seat:-1,
list:''
}
},
created(){
this.list=new Array(this.number)
},
methods: {
hideKeyboard() {
// 输入完成隐藏键盘
document.activeElement.blur() // ios隐藏键盘
this.$refs.input.blur() // android隐藏键盘
},
keydown(e){//当按下按键时
console.log(e)
//alert(JSON.stringify(e))
},
keyup(){ //按键松开时运行
this.seat+=1
this.$refs.input.value = this.value
if (this.value.length >= this.number){
this.hideKeyboard()
this.seat= this.number
}
this.handleSubmit()
},
handleSubmit() { //返回信息
this.$emit('returnresult',this.value)
},
onClean(){ //清除
this.value=''
this.seat=-1
},
onClick(index){//点击
this.seat=index
}
}
}
</script>
<style scoped lang="less">
.security-code-container {
margin: 0;
padding:20px 0;
display: flex;
justify-content: center;
.field-wrap {
list-style: none;
display: block;
border: 1px solid #eee;
height:25px;
width:25px;
font-size:18px;
text-align: center;
overflow: hidden;
background-color: #fff;
margin-right:5px;
.char-field {
font-style: normal;
}
&.on{
border:1px solid #0E88EF;
}
}
}
.input-code {
width:100%;
height:30px;
position:absolute;
left:-999999999999px;
opacity:0;
z-index:-1;
}
.clean{
width:100%;
box-sizing: border-box;
text-align: right;
color: #0E88EF;
font-size: 12px;
padding:0 10px;
}
</style>
2.第二种实现方式
1.使用css3隐藏输入框
<template>
<div>
<div class="code-input-main">
<div
class="code-input-main-item"
v-for="(item,index) in codeList"
:class="{'on':seat==index}"
:key="index"
@click="onClick(index)"
>{{code[index] ||''}}</div>
<input class="code-input-input" ref="input" v-model="code" :maxlength="codeLength" type="tel" />
</div>
<div class="clean"><span @click.stop="onClean">清除</span></div>
</div>
</template>
<script>
export default {
name:'VueVercode',
props: {
codeLength: {
default: 10,
type: Number
}
},
data() {
return {
codeList: [],
code:'',
seat:0,
}
},
mounted() {
// 定义一个数组用于循环
this.codeList = new Array(this.codeLength).fill('')
},
watch: {
// 截取字符长度
code() {
if(this.code.length <=0){
this.seat=0
}else{
this.seat+=1
}
if (this.code.length > this.codeLength) {
this.code = this.code.substring(0, this.codeLength)
}
this.$emit('returnresult',this.code)
}
},
methods: {
getCode() {
return this.code
},
onClean(){ //清除
this.code=''
},
onClick(index){
this.seat=index
}
}
}
</script>
<style scoped>
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none !important;
margin: 0;
}
.code-input-main {
width:100%;
box-sizing: border-box;
display: flex;
flex-direction: row;
justify-content: space-around;
position: relative;
padding:20px 0 0;
}
.code-input-input {
height:25px;
width: 100%;
position: absolute;
border:none;
outline: none;
color: transparent;
background-color:transparent;
text-shadow: 0 0 0 transparent;
caret-color: transparent;
opacity:0
}
.code-input-main-item {
width:25px;
height:25px;
line-height:25px;
margin-right:5px;
padding:0;
opacity: 0.8;
border: solid #eee 1px;
text-align: center;
font-size:14px;
color: #323232;
}
.on{
border:1px solid #0E88EF;
}
.clean{
width:100%;
box-sizing: border-box;
text-align: right;
color: #0E88EF;
font-size: 12px;
margin-top:20px;
padding:0 10px;
}
</style>
3.第三种实现方式
完全和单输入框一样的操作,甚至可以插入覆盖:
1,限制输入数字
2,正常输入
3,backspace删除
4,paste任意位置粘贴输入
5,光标选中一个数字,滚轮可以微调数字大小,限制0-9
6,123|456 自动覆盖光标后输入的字符,此时光标在3后,继续输入111,会得到123111,而不用手动删除456
7,封装成vue单文件组件,方便任意调用。
8.实现了键盘的keydown/keyup/paste/input和鼠标滚轮mousewheel事件
使用了6个输入框的方案来实现。
<!--四位验证码输入框组件-->
<template>
<div class="input-box">
<div class="input-content" @keydown="keydown($event)" @keyup="keyup($event)" @progress="keyup" @paste="paste" @mousewheel="mousewheel" @input="inputEvent">
<input max="9" min="0" maxlength="1" data-index="0" v-model="input[0]" type="tel" ref="firstinput"/>
<template v-for="(itme,index) in isNumber">
<input :key="index" v-if="index>0" max="9" min="0" maxlength="1" :data-index="index" v-model="input[index]" type="tel" />
</template>
</div>
<div class="clean"><span @click.stop="onClean">清除</span></div>
</div>
</template>
<script>
export default {
data() {
return {
pasteResult: []
}
},
props:{
code:{
typeof:Array,
default:[]
},
isNumber:{
typeof:Number,
default:10 //输入框个数
}
},
computed: {
input() {
if (this.code && Array.isArray(this.code) && this.code.length === this.isNumber) {
return this.code
} else if (/^\d{`${this.isNumber}`}$/.test(this.code.toString())) {
return this.code.toString().split('')
} else if (this.pasteResult.length === this.isNumber) {
return this.pasteResult
} else {
return new Array(this.isNumber)
}
}
},
methods: {
// 解决一个输入框输入多个字符
inputEvent(e) { //输入框
var index = e.target.dataset.index * 1
var el = e.target
el.value = el.value.replace(/Digit|Numpad/i, '').replace(/1/g, '').slice(0, 1)
this.$set(this.input, index, el.value)
},
keydown(e) { //键盘按下
var index = e.target.dataset.index * 1
var el = e.target
if (e.key === 'Backspace') {
if (this.input[index].length > 0) {
this.$set(this.input, index, '')
} else {
if (el.previousElementSibling) {
el.previousElementSibling.focus()
this.$set(this.input, index - 1, '')
}
}
} else if (e.key === 'Delete') {
if (this.input[index].length > 0) {
this.$set(this.input, index, '')
} else {
if (el.nextElementSibling) {
this.$set(this.input, index = 1, '')
}
}
if (el.nextElementSibling) {
el.nextElementSibling.focus()
}
} else if (e.key === 'Home') {
el.parentElement.children[0] && el.parentElement.children[0].focus()
} else if (e.key === 'End') {
el.parentElement.children[this.input.length - 1] && el.parentElement.children[this.input.length - 1].focus()
} else if (e.key === 'ArrowLeft') {
if (el.previousElementSibling) {
el.previousElementSibling.focus()
}
} else if (e.key === 'ArrowRight') {
if (el.nextElementSibling) {
el.nextElementSibling.focus()
}
} else if (e.key === 'ArrowUp') {
if (this.input[index] * 1 < 9) {
this.$set(this.input, index, (this.input[index] * 1 + 1).toString())
}
} else if (e.key === 'ArrowDown') {
if (this.input[index] * 1 > 0) {
this.$set(this.input, index, (this.input[index] * 1 - 1).toString())
}
}
},
keyup(e) { //键盘弹开
console.log(e,'==============================')
var index = e.target.dataset.index * 1
var el = e.target
// 解决输入e的问题
el.value = el.value.replace(/Digit|Numpad/i, '').replace(/1/g, '').slice(0, 1)
alert(e.code)
if (/Digit|Numpad/i.test(e.code)) {
// 必须在这里符直,否则输入框会是空值
this.$set(this.input, index, e.code.replace(/Digit|Numpad/i, '')) //获取值是多少
console.log(this.input,'--------键盘弹开-----------')
let result=this.input.join('').trim()
this.$emit('returnresult',result)//返回结果
el.nextElementSibling && el.nextElementSibling.focus()
if (index === this.isNumber-1) {
if (this.input.join('').length === this.isNumber) {
document.activeElement.blur()
this.$emit('complete', this.input)
}
}
} else {
if (this.input[index] === '') {
this.$set(this.input,index,'')
}
}
},
mousewheel(e) { //滚动事件
var index = e.target.dataset.index
if (e.wheelDelta > 0) {
if (this.input[index] * 1 < 9) {
this.$set(this.input, index, (this.input[index] * 1 + 1).toString())
}
} else if (e.wheelDelta < 0) {
if (this.input[index] * 1 > 0) {
this.$set(this.input, index, (this.input[index] * 1 - 1).toString())
}
} else if (e.key === 'Enter') {
if (this.input.join('').length === this.isNumber) {
document.activeElement.blur()
this.$emit('complete', this.input)
}
}
},
paste(e) {
// 当进行粘贴时
e.clipboardData.items[0].getAsString(str => {
if (str.toString().length === this.isNumber) {
this.pasteResult = str.split('')
document.activeElement.blur()
let result=this.pasteResult .join('').trim()
this.$emit('returnresult',result)//返回结果
} else {
// 如果粘贴内容不合规,清除所有内容
this.input[0] = new Array(this.isNumber)
}
})
},
onClean(){ //清除
this.pasteResult=[] //清除所有内容
this.$emit('complete', this.input)
this.$refs.firstinput.focus()
this.$emit('returnresult','')//返回结果
}
},
mounted() {
// 等待dom渲染完成,在执行focus,否则无法获取到焦点
this.$nextTick(() => {
this.$refs.firstinput.focus()
})
},
}
</script>
<style lang="less" scope>
.input-box {
width:100%;
position: relative;
padding:10px 0;
.input-content {
width:100%;
height:40px;
display: flex;
align-items: center;
justify-content: space-between;
input {
color: inherit;
font-family: inherit;
border: 0;
outline: 0;
border: 1px solid #eee;
height:25px;
width:25px;
font-size:18px;
text-align: center;
overflow: hidden;
outline:none;
background:none;
}
}
.clean{
width:100%;
text-align: right;
color: #0E88EF;
font-size: 12px;
margin-top:20px;
}
}
input::-webkit-outer-spin-button,input::-webkit-inner-spin-button {appearance: none;margin: 0;}
input::-webkit-outer-spin-button,input::-webkit-inner-spin-button {-webkit-appearance: none;}
input[type="number"] {-moz-appearance: textfield;-webkit-appearance: none;margin: 0;}
</style>
4.如何引用组件
<template>
<div>
<div class="box">
<div class="h3">请输入兑换码</div>
<vercode @returnresult="returnresult"></vercode>
<!-- <digital-input-box @returnresult="returnresult"></digital-input-box>
<securityCode @returnresult="returnresult"></securityCode> -->
</div>
<div class="but-box">
<van-button :loading="loading" @click="onCxchange" round size="large" loading-text="加载中..." type="info" class="sjht-shadow" :disabled="disabled">兑换</van-button>
</div>
</div>
</template>
<script>
// import digitalInputBox from './components/digitalInputBox.vue'
// import securityCode from './components/securityCode.vue'
import vercode from './components/vercode.vue'
export default {
name: 'Cxchange', //公众号首页
components:{
// digitalInputBox,
// securityCode,
vercode
},
data() {
return {
disabled:true,
loading:false,
couponeCode:''
}
},
methods:{
onCxchange(){
if(this.couponeCode.length>=9){
this.disabled=false
}else{
this.disabled=true
}
this.loading=true
this.disabled=true
//这里是填写你的AJAX代码
},
returnresult(data){
console.log(data,'-----------------')
this.couponeCode=data
if(this.couponeCode.length>=9){
this.disabled=false
}else{
this.disabled=true
}
}
}
}
</script>
<style lang="less" scope>
.box{
width:95%;
height: 142px;
background: #FFFFFF;
border-radius: 7px;
margin:20px auto;
box-sizing: border-box;
padding:14px;
.h3{
width:100%;
height: 21px;
font-size: 15px;
font-family: PingFangSC-Semibold, PingFang SC;
font-weight: 600;
color: #333333;
line-height: 21px;
}
}
.but-box{
width: 90%;
margin:0 auto;
position: relative;
}
</style>
GitHub 加速计划 / vu / vue
207.54 K
33.66 K
下载
vuejs/vue: 是一个用于构建用户界面的 JavaScript 框架,具有简洁的语法和丰富的组件库,可以用于开发单页面应用程序和多页面应用程序。
最近提交(Master分支:2 个月前 )
73486cb5
* chore: fix link broken
Signed-off-by: snoppy <michaleli@foxmail.com>
* Update packages/template-compiler/README.md [skip ci]
---------
Signed-off-by: snoppy <michaleli@foxmail.com>
Co-authored-by: Eduardo San Martin Morote <posva@users.noreply.github.com> 4 个月前
e428d891
Updated Browser Compatibility reference. The previous currently returns HTTP 404. 5 个月前
更多推荐
已为社区贡献3条内容
所有评论(0)