vue 触摸屏虚拟键盘简单示例分享
效果图
1、字母键盘
2、数字键盘
业务需求只使用到了数字、字母两种键盘,符号以及大小写未实现
组件代码
<template>
<div class="container" @click="isKeyClick = true">
<template v-if="!keyBoardType || keyBoardType == 'DIGIT'">
<div
v-for="item in [1, 2, 3, 4, 5, 6, 7, 8, 9]"
:key="item"
class="child keyBtn"
:class="rowCount ? rowCount : 'three'"
>
{{ item }}
</div>
<div :class="rowCount ? rowCount : 'three'" class="child keyBtn">
清空
</div>
<div :class="rowCount ? rowCount : 'three'" class="child keyBtn">0</div>
<div :class="rowCount ? rowCount : 'three'" class="child keyBtn">
删除
</div>
</template>
<template v-else-if="keyBoardType == 'LETTER'">
<div
v-for="letter in alphabet"
:key="letter"
class="child keyBtn"
:class="rowCount ? rowCount : 'three'"
>
{{ letter }}
</div>
<div class="child keyBtn delBtn" :class="rowCount ? rowCount : 'three'">
删除
</div>
</template>
</div>
</template>
<script>
export default {
data() {
return {
alphabet: Array.from({ length: 26 }, (_, i) =>
String.fromCharCode("A".charCodeAt(0) + i)
),
//用来判断点击的是否为键盘
isKeyClick: false,
inputTextareaEle: null,
tagNameList: ["input", "textarea"],
};
},
props: ["keyBoardType", "rowCount"], //DIGIT,LETTER 数字、字母键盘
mounted() {
this.inputTextareaEle = document.querySelectorAll(
this.tagNameList.join(",")
);
const inputTextareaEle = this.inputTextareaEle;
this.blurHandler = (ele) => {
//如果输入框失去焦点,则判断用户点击的是否为虚拟键盘
ele.addEventListener("blur", () => {
if (this.isKeyClick) ele.focus();
});
};
inputTextareaEle.forEach(this.blurHandler);
//点击后
this.mousedownHandler = (e) => {
if (
typeof e.target.className == "string" &&
e.target.className.includes("keyBtn")
) {
this.isKeyClick = true;
let keyVal = e.target.textContent.trim();
if (keyVal == "删除") {
this.innerCont("", "删除");
return;
}
if (keyVal == "清空") {
this.innerCont("", "清空");
return;
}
this.innerCont(keyVal);
} else {
this.isKeyClick = false;
}
};
document.addEventListener("mousedown", this.mousedownHandler);
},
unmounted() {
//卸载全局监听
document.removeEventListener("mousedown", this.mousedownHandler);
},
methods: {
innerCont(value, type) {
//type:清空、删除
const adom = document.activeElement;
if (adom.tagName != "INPUT") {
return;
}
adom.focus();
const activeValue = adom.value.substr(
adom.selectionStart,
adom.selectionEnd - adom.selectionStart
);
const startPos =
(type == "删除" && activeValue) || type != "删除"
? adom.selectionStart
: adom.selectionStart - 1;
const endPos = adom.selectionEnd;
// 保存滚动条
const restoreTop = adom.scrollTop;
adom.value =
adom.value.substring(0, startPos) +
value +
adom.value.substring(endPos, adom.value.length);
if (type == "清空") {
adom.value = "";
}
if (restoreTop > 0) adom.scrollTop = restoreTop;
adom.focus();
adom.selectionStart = startPos + value.length;
adom.selectionEnd = startPos + value.length;
//通过手动触发input事件 实现v-model更新
adom.dispatchEvent(new Event("input"));
},
},
};
</script>
<style scoped>
.container {
display: flex;
flex-wrap: wrap;
}
.child {
margin: 3px;
background-color: var(--main-default-color-2);
height: 50px;
line-height: 50px;
align-items: center;
border-radius: 5px;
}
.three {
flex: 0 0 calc(33.333% - 10px); /* 10px是子div之间的间距 */
}
.four {
flex: 0 0 calc(25% - 10px);
}
.five {
flex: 0 0 calc(20% - 10px);
}
.delBtn {
background-color: var(--main-warning-color);
color: #fff;
}
</style>
使用
<KeyBoard
@click="$refs.serchInp.focus()" //可根据实际需求设置焦点
:keyBoardType="'LETTER'" //DIGIT,LETTER 数字、字母键盘
:rowCount="'five'" //根据该参数设置按键的class,可以在组件中通过计算样式属性优化这段代码
></KeyBoard>
import KeyBoard from "@/components/KeyBoard.vue";
components: { KeyBoard },