前言
大家好 我是歌谣 今天给大家带来vue3的功能关于键盘的实现
封装的小组件代码
<template>
<div class="key-container">
<div class="keyboard" @click.stop="handleKeyPress">
<div class="key-row">
<div class="cell-box">
<div class="key-cell" data-num="1">1</div>
</div>
<div class="cell-box">
<div class="key-cell" data-num="2">2</div>
</div>
<div class="cell-box">
<div class="key-cell" data-num="3">3</div>
</div>
<div class="cell-box">
<div class="key-cell" data-num="4">4</div>
</div>
</div>
<div class="key-row">
<div class="cell-box">
<div class="key-cell" data-num="5">5</div>
</div>
<div class="cell-box">
<div class="key-cell" data-num="6">6</div>
</div>
<div class="cell-box">
<div class="key-cell" data-num="7">7</div>
</div>
<div class="cell-box">
<div class="key-cell" data-num="8">8</div>
</div>
</div>
<div class="key-row">
<div class="cell-box">
<div class="key-cell" data-num="9">9</div>
</div>
<div class="cell-box">
<div class="key-cell" data-num="0">0</div>
</div>
<div class="cell-box">
<div class="key-cell" data-num="C">清空</div>
</div>
<div class="cell-box">
<div class="key-cell" data-num="S">报工</div>
</div>
</div>
<!-- <div class="key-row">
<div class="cell-box">
<div class="key-cell" data-num=".">.</div>
</div>
<div class="cell-box">
<div class="key-cell" data-num="0">0</div>
</div>
<div class="cell-box">
<div class="key-cell key-delete" data-num="C">删除</div>
</div>
<div class="cell-box">
<div class="key-cell" data-num></div>
</div>
<div class="cell-box">
<div class="key-cell" data-num></div>
</div>
<div class="cell-box">
<div class="key-cell" data-num></div>
</div>
</div> -->
<!-- <div class="key-right-clear">
<div class="key-clear" data-num="C">清空</div>
</div>
<div class="key-right-confirm">
<div class="key-confirm" data-num="S">报工</div>
</div> -->
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
const props = defineProps({
//默认传入的数据线
clickTime: {
type: Number,
},
//默认传入的索引
fatherNum: {
type: Number,
default: 0
}
});
const emit = defineEmits(["clearEvent", "deleteEvent", "numberEvent", "confirmEvent"])
const num = ref(0)
const click = ref(0)
const { fatherNum, clickTime } = props
const handleKeyPress = (e) => {
console.log(e, "is")
const number = e.target.dataset.num;
console.log(number, "is")
// 不同的按键处理逻辑
// num为空,直接返回
if (!number) return;
switch (String(number)) {
// 删除键
case "D":
handleDeleteKey();
break;
// 清空键
case "C":
handleClearKey();
break;
// 确认键
case "S":
handleConfirmKey();
break;
default:
handleNumberKey(number);
break;
}
}
console.log(fatherNum, "fatherNum is")
const handleDeleteKey = () => {
console.log(fatherNum, "fatherNum is")
num.value = fatherNum; // 这一步是为了让this.num能及时接收this.fatherNum的值,解决第二行输入后去删除第一行值出现的bug
const S = num.value;
console.log(S, "S is")
// if (!S.toString()) return false;
if (!S.toString().length) return false;// 如果没有输入(或者长度为0),直接返回
// 否则删除最后一个
num.value = S.toString().substring(0, S.toString().length - 1);
console.log(num.value, "value is")
emit("deleteEvent", num); //把删除处理后了的值返回给父组件
}
// 处理清空键
const handleClearKey = () => {
num.value = 0; // 清空就赋值一个‘’,然后返回给父组件
emit("clearEvent", num);
}
// 处理数字
const handleNumberKey = (number) => {
// 确保处理的this.num是父组件传入的this.fatherNum
num.value = fatherNum;
click.value = clickTime;
const S = num.value; // 拿到父组件点击的那个输入框的值
// 第一次不能输入.
if (click == 1) {
if (number == ".") return;
}
//前提是并非刚点击了input
if (click != 1) {
// 若this.num有且只有一位数并且是0,则输入的不是.,就返回
if (S && S.length == 1 && S[0] == 0 && number != ".") return;
if (S) {
let index = S.toString().indexOf(".");
// 如果存在.,则不能再次输入.
if (index > -1 && number == ".") return;
// 小数位数不能超过2位
if (S && index > -1 && S.length - 2 > index) return;
}
}
if (!S) {
//如果是首次输入,则原有的this.num是undefined,不需要拼接上
num.value = `${number}`;
} else {
num.value = `${S}${number}` // 在原有的基础上将点击的那个数字按键的数字加在原有数字字符串末尾,此处是为删除提供数据
}
// 此处不能使用正则表达式判断
emit("numberEvent", number); // 注意传的是点击的那个数字字符串,不是处理后的整个数字字符串
}
// 确认键
const handleConfirmKey = () => {
// 这一步是为了解决一进页面,input框内有值,直接点确认出现数据情况,再次点数据出现undefined问题(如果没有该赋值,this.num为undefined)
// num.value = fatherNum;
// const S = num.value;
// // 如果输入的数字最后一位是.,则删除
// if (S) {
// let index = S.toString().indexOf(".");
// if (index == S.length - 1) {
// num.value = S.substring(0, S.length - 1);
// }
// }
emit("confirmEvent");
}
</script>
<style lang="less" scoped>
.key-container {
width: 100%;
height: 3.8rem;
display: flex;
display: -webkit-flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
font-weight: bold;
color: rgba(51, 51, 51, 0.85);
.keyboard {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
background-color: #fff;
padding: 0.05rem;
background: rgba(240, 240, 240);
box-sizing: border-box;
.key-row {
display: flex;
display: -webkit-flex;
position: relative;
line-height: 1rem;
&::before {
content: "";
position: absolute;
left: 0;
top: 0;
right: 0;
height: 1px;
color: #d5d5d6;
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
-webkit-transform: scaleY(0.5);
transform: scaleY(0.5);
}
}
.cell-box {
font-size: 0.42rem;
font-weight: bold;
flex: 1;
-webkit-box-flex: 1;
text-align: center;
position: relative;
padding: 0.05rem;
box-sizing: border-box;
&::after {
content: "";
position: absolute;
overflow: hidden;
top: 0;
right: 0;
bottom: 0;
height: 200%;
color: #d5d5d6;
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
-webkit-transform: scaleY(0.5);
transform: scaleY(0.5);
}
&:nth-last-child(1)::after {
border-right: 0;
}
}
.key-cell {
background: #fff;
border-radius: 0.1rem;
}
.key-delete {
font-size: 0.38rem;
}
.key-right-confirm {
font-size: 0.38rem;
padding: 0.05rem;
position: absolute;
text-align: center;
height: 2.1rem;
width: 23%;
line-height: 2.1rem;
background: rgba(240, 240, 240);
z-index: 5;
right: 0.05rem;
bottom: 0.05rem;
}
.key-right-clear {
font-size: 0.38rem;
padding: 0.05rem;
position: absolute;
text-align: center;
height: 2.1rem;
width: 23%;
line-height: 2.1rem;
background: rgba(240, 240, 240);
z-index: 5;
right: 0.05rem;
top: 0.05rem;
}
.key-confirm {
border-radius: 0.1rem;
background: #1561b3;
color: #fff;
}
.key-clear {
border-radius: 0.1rem;
background: #fff;
}
}
}</style>
父组件使用
<Numberkey v-show="keyShow" v-model:fatherNum="formState.user[type]" :clickTime="clickTime" @confirmEvent="confirmEvent"
@numberEvent="numberEvent" @clearEvent="clearEvent" @deleteEvent="deleteEvent"></Numberkey>
方法和变量
const formState = ref({
user: {
planned: 0,
qualified: 0,
unqualified: 0,
scrap: 0,
teamcode:0
},
});
const numberEvent = (res) => {
console.log(res, "res is")
formState.value.user[`${type.value}`] =
clickTime.value == 1
? `${res}`
: `${formState.value.user[`${type.value}`]}${res}`;
//此处设置是为了让键盘点击的值能立马显示在input框中,如没有此设置,只有点击确认键盘隐藏时才会显示数据
keyShow.value = false;
keyShow.value = true;
clickTime.value = 2;
}
const handledata = (datatype) => {
keyShow.value = true;
type.value = datatype
}
// 点击确认键
const confirmEvent = (res) => {
// console.log(formState, type, res, "type is")
// formState.value.user[`${type.value}`] = res.value;
// 点击确认,收起键盘
numberNew.value++
if (numberNew.value > baseArray.length - 1) {
router.push({
name: "index"
});
} else {
router.push({
name: baseArray[0].route
});
}
}
const clearEvent = (res) => {
formState.value.user[`${type.value}`] = res.value; // 清除,子组件传过来的是‘’
// 此处设置是为了让键盘点击的值能立马显示在input框中,如没有此设置,只有点击确认键盘隐藏时才会显示数据
keyShow.value = false;
keyShow.value = true;
}
// 点击删除键
const deleteEvent = (res) => {
formState.value.user[`${type.value}`] = res.value;
// 此处设置是为了让键盘点击的值能立马显示在input框中,如没有此设置,只有点击确认键盘隐藏时才会显示数据
keyShow.value = false;
keyShow.value = true;
}