分格输入框
1、效果预览
2、代码
import { ref } from "vue";
const value = ref("");
const counts = ref(4);
const isFocus = ref(false);
const inputFocus = () => {
isFocus.value = true;
};
const inputBlur = () => {
isFocus.value = false;
};
const handleInput = (e) => {
value.value = e.target.value = e.target.value.replace(/[^\d]/g, "");
};
</script>
<template>
<div>
<div class="content">
<input
class="input"
type="text"
:value="value"
:maxlength="counts"
@focus="inputFocus"
@blur="inputBlur"
@input="handleInput"
/>
<div class="wrap">
<div
v-for="count in counts"
:key="count"
:class="[
'wrap_item',
isFocus &&
(count - 1 === value.length ||
(value.length === counts && count === counts))
? 'active'
: '',
]"
>
{{ value[count - 1] || "" }}
</div>
</div>
</div>
</div>
</template>
<style scoped>
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
.content {
position: relative;
margin: 40px auto;
height: 50px;
width: 300px;
}
.input {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
opacity: 0;
}
.wrap {
display: flex;
justify-content: space-between;
width: 100%;
height: 100%;
}
.wrap_item {
border: 1px solid grey;
width: 50px;
text-align: center;
line-height: 50px;
font-size: 30px;
}
.wrap_item.active {
position: relative;
border: 1px solid blue;
}
.wrap_item.active::after {
content: " ";
width: 0;
border-right: 2px solid grey;
position: absolute;
left: 50%;
top: 10%;
bottom: 10%;
animation: mark 1s infinite ease;
}
@keyframes mark {
0% {
opacity: 0;
}
50% {
opacity: 1;
}
100% {
opacity: 0;
}
}
</style>