vue3在元素上绑定自定义事件弹出虚拟键盘
最近开发中遇到一个需求:
焊接机器人的屏幕上集成web前端网页, 但是没有接入键盘。这就需要web端开发一个虚拟键盘,在网上找个很多虚拟键盘没有特别适合,索性自己写个简单的
图片:

代码:
(代码可能比较垃圾冗余,也没时间优化,凑合看吧)
第一步:创建键盘组件
为了方便使用,我将键盘写成组件的方式,在app.vue中引入可以全局使用
<template><el-dialogv-model="isShows"append-to-body="true"width="80%"@close="dialogClose"><divclass="keyboard_pop"@click.self="isShows = false"><div class="input"><spanv-if="!showText"class="placeholder">请输入内容</span><p v-else>{{ showText }}</p></div><div class="keyboard"><divv-for="(row, index) in keyList":key="index"class="keyRow"><divv-for="(key, keyIndex) in row":key="keyIndex":class="{delete: key === 'Delete',capslock: key === 'Caps',space: key === 'Space',capsed: key === 'Caps' && hasCapsed,li: true,}"@click="clickKey(key)">{{ key }}</div></div></div></div></el-dialog>
</template>
<script setup name="template">import useHomeStore from "@/stores/home"; //引入仓库import { storeToRefs } from "pinia"; //引入pinia转换import { ElMessage } from "element-plus";const userInfoStore = useHomeStore();const { isShows, showText, inputType } = storeToRefs(userInfoStore); // 响应式const emits = defineEmits(["updatekey"]);const keyvalue = ref(showText); //键盘输入值 this.keyboardtextconst normalKeyList = ref([["1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "-", "="],["q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "[", "]", "\\"],["a", "s", "d", "f", "g", "h", "j", "k", "l", ";", "'", "Enter"],["z", "x", "c", "v", "b", "n", "m", ",", ".", "/"],["Caps", "Space", "Delete"],]); //正常键盘列表const capsedKeyList = ref([["1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "-", "="],["Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", "[", "]", "\\"],["A", "S", "D", "F", "G", "H", "J", "K", "L", ";", "'", "Enter"],["Z", "X", "C", "V", "B", "N", "M", ",", ".", "/"],["Caps", "Space", "Delete"],]); //大写键盘列表const keyList = ref(normalKeyList.value); //键盘列表const hasCapsed = ref(false); //是否大写const clickKey = (key) => {if (inputType.value == "number") {const flag = ["0","1","2","3","4","5","6","7","8","9",'.',"Enter","Delete",].includes(key);if (!flag) {return ElMessage({message: "请输入数字",type: "warning",});}}switch (key) {case "Enter":userInfoStore.showText = keyvalue.value;userInfoStore.clickEnter();break;case "Delete":let kbt = keyvalue.value;keyvalue.value = kbt.length ? kbt.substring(0, kbt.length - 1) : kbt;break;case "Space":keyvalue.value += " ";break;case "Caps":hasCapsed.value = !hasCapsed.value;keyList.value = hasCapsed.value ? capsedKeyList.value : normalKeyList.value;break;default:keyvalue.value += key;break;}userInfoStore.showText = keyvalue.value;const dialogClose = () => {//遮罩层关闭userInfoStore.dialogClose();};};
</script>
<style lang="scss" scoped>.input {min-height: 80px;border: 1px solid #ccc;border-radius: 5px;margin-bottom: 30px;padding: 10px;}.keyboard_pop {width: 100%;}.keyRow {display: flex;justify-content: space-between;align-items: center;margin-bottom: 10px;}.keyboard {margin: 0;padding: 0;list-style: none;user-select: none;background: #fff;width: 100%;padding: 5px 15px;overflow: auto;.li {padding: 8px 18px;text-align: center;background: #fff;border-radius: 15px;font-size: 18px;font-weight: 500;box-shadow: 0 3px 6px 0px #cac9c9;&:hover {cursor: pointer;background: #03ba82;color: #fff;}&:active {top: 1px;left: 1px;}}.delete {width: 100px;}.space {width: 300px;}.capsed {position: relative;top: 1px;left: 1px;border-color: #e5e5e5;cursor: pointer;}}
</style>
第二步:注册自定义事件
(给元素绑定自定义事件,input获取光标直接可以显示虚拟键盘,方便操作!)
const isInput = (dom) => {// 检查dom是否是input元素if (dom.tagName === "INPUT") {return dom;}// 如果不是input元素,且有子节点,则递归查找子节点if (dom.children) {for (let child of dom.children) {let input = isInput(child);if (input) {return input; // 如果找到input元素,立即返回}}}// 如果没有找到input元素,返回nullreturn null;
};import pinia from "@/stores/index";
import useHomeStore from "@/stores/home"; //引入仓库
const userInfoStore = useHomeStore(pinia);export const showKeyboard = {mounted(el, binding) {const input = isInput(el);if (!input) {return console.log("绑定错误,没有input元素");}//保存input元素userInfoStore.inputDom = input;//给input注册input事件input.addEventListener("focus", function (e) {console.log("聚焦了");console.dir(e);//保存input输入框的类型userInfoStore.inputType = e.target.type;userInfoStore.inputDom = e.target;userInfoStore.isShows = true;userInfoStore.showText = e.target.value;e.target.blur();});// input.addEventListener("blur", function (e) {// console.log("失去聚焦了");// // userInfoStore.isShows = false;// });},
};
第三步:pinia保存全局变量
(全局保存变量,各个input输入的值方便保存)
import { defineStore } from "pinia";const useHomeStore = defineStore("Home", {// defineStore('userInfo',{}) Home就是这个仓库的名称namestate: () => ({inputDom: null,isShows: false,showText: "",inputType: "",}),actions: {//点击键盘确定clickEnter() {//this.inputDom.change()console.log(this.showText);this.inputDom.value = JSON.parse(JSON.stringify(this.showText))console.dir(this.inputDom);//手动触发change事件// 什么是dispatchEvent// 向一个指定的事件目标派发一个事件,// 并以合适的顺序同步调用目标元素相关的事件处理函数。// 标准事件处理规则(包括事件捕获和可选的冒泡过程)// 同样适用于通过手动的使用dispatchEvent()方法派发的事件。this.inputDom.dispatchEvent(new Event("input"));this.inputDom.dispatchEvent(new Event("change"));this.showText = "";this.inputDom.blur();this.isShows = false;this.inputDom = null;this.inputType = "";},//遮罩层关闭dialogClose() {this.showText = "";this.isShows = false;this.inputDom.blur();this.inputDom = null;this.inputType = "";},},
});export default useHomeStore;
相关文章:
vue3在元素上绑定自定义事件弹出虚拟键盘
最近开发中遇到一个需求: 焊接机器人的屏幕上集成web前端网页, 但是没有接入键盘。这就需要web端开发一个虚拟键盘,在网上找个很多虚拟键盘没有特别适合,索性自己写个简单的 图片: 代码: (代码可能比较垃圾冗余,也没时间优化,凑合看吧) 第一步:创建键盘组件 为了方便使用…...
VMware 上安装 CentOS 7 教程 (包含网络设置)
**建议先看一些我安装VMware的教程,有些网络配置需要做一下 1.打开VMware,创建虚拟机 2.勾选自定义,点击下一步 3.点击下一步 4.勾选“稍后安装操作系统”,点击下一步 5.勾选linux,勾选centos7,点击下一步…...
算法 day4 【双指针、快慢指针、环形链表】链表下
⚡刷题计划day4继续,可以点个免费的赞哦~ 下一期将会开启哈希表刷题专题,往期可看专栏,关注不迷路, 您的支持是我的最大动力🌹~ 目录 ⚡刷题计划day4继续,可以点个免费的赞哦~ 下一期将会开启哈希表刷题…...
智能音箱的工作原理
智能音箱的工作原理主要涉及到硬件和软件两个层面的协同工作,以及多个关键技术环节的配合。以下是对智能音箱工作原理的详细解析: 一、硬件层面 智能音箱的硬件组成通常包括主控芯片、麦克风阵列、扬声器、Wi-Fi模块和电源等部分。 主控芯片࿱…...
国际金融入门:国际收支与平衡表解析
在全球化的经济体系中,国际金融已成为我们日常生活不可或缺的一部分。了解国际金融的基础知识,可以帮助我们更好地理解世界经济的动态和趋势。今天,我们将深入探讨国际收支及其平衡表,以及它们是如何影响国家经济。 国际收支&…...
Modbus转BACnet/IP网关的技术实现与应用
引言 随着智能建筑和工业自动化的快速发展,不同通信协议之间的数据交换也变得日益重要。Modbus和BACnet/IP是两种广泛应用于自动化领域的通信协议,Modbus以其简单性和灵活性被广泛用于工业自动化,而BACnet/IP则在楼宇自动化系统中占据主导地…...
数据库连接断开后,DBAPI的数据源如何自动重连
现象 在使用DBAPI的过程中,如果网络抖动导致数据库连接不上,发现DBAPI的数据源不能重连,必须重启DBAPI才能连上数据库 解决办法 在数据源的连接池参数配置druid.breakAfterAcquireFailurefalse注意在企业版的4.1.1及以上版本才可以配置连接…...
Microsoft 365 Office BusinessPro LTSC 2024 for Mac( 微软Office办公套件)
Microsoft 365 Office BusinessPro LTSC 2024是一款专为商业用户设计的办公软件套件,它集成了Word、Excel、PowerPoint等核心应用,并特别包含了Microsoft Teams这一强大的协作工具。Teams将聊天、会议、文件共享、任务管理等功能整合到一个平台上&#x…...
svelte - 1. 基础知识
svelte中文官网 vue和svelt语法对比 掘金-svelte入门简介 文章目录 1、基本页面框架2、动态属性3、嵌套组件4、@html: 插入html标签,显示真实dom元素5、点击事件 on:click={handleClick}6、响应式声明7、父子组件通信8、if-else(1)if(2)if - else(3)if - else if - else…...
挖掘基于边缘无线协同感知的低功耗物联网 (LPIOT) 的巨大潜力
关键词:边缘无线协同感知、低功耗物联网(LPIOT)、无线混合组网、用电监测、用电计量、多角色、计量插座、无线场景感知、多角色运用、后台边缘层,网络边缘层,场景能效管理,场景能耗计算 在数字化和智能化日益加速的今天ÿ…...
iOS开发设计模式篇第一篇MVC设计模式
目录 1. 引言 2.概念 1.Model 1.职责 2.实现 3.和Controller通信 1.Contrller直接访问Model 2.通过委托(Delegate)模式 3.通知 4.KVO 4.设计的建议 2.View 1.职责 2.实现 3.和Controller通信 1. 目标-动作(Target-Action)模式 2…...
【React】全面解析:从基础知识到高级应用,掌握现代Web开发利器
文章目录 一、React 的基础知识1. 什么是 React?2. React 的基本概念3. 基本示例 二、React 的进阶概念1. 状态(State)和属性(Props)2. 生命周期方法(Lifecycle Methods)3. 钩子(Hoo…...
神经网络之卷积神经网络
目录 一、卷积神经网络概述:1.卷积层:1.1卷积核与神经元:1.2卷积层作用:1.3多输出通道概念: 2.池化层:2.1池化层作用: 3.隐藏层与卷积层、池化层关系: 一、卷积神经网络概述…...
【Vue实战教程】之Vue工程化项目详解
Vue工程化项目 随着多年的发展,前端越来越模块化、组件化、工程化,这是前端发展的大趋势。webpack是目前用于构建前端工程化项目的主流工具之一,也正变得越来越重要。本章节我们来详细讲解一下如何使用webpack搭建Vue工程化项目。 1 使用we…...
DBeaver Ultimate 22.1.0 连接数据库(MySQL+Mongo+Clickhouse)
前言 继续书接上文 Docker Compose V2 安装常用数据库MySQLMongo,部署安装好之后我本来是找了一个web端的在线连接数据库的工具,但是使用过程中并不丝滑,最终还是选择了使用 DBeaver ,然后发现 mongo 还需要许可,又折…...
探索PyMuPDF:Python中的强大PDF处理库
探索PyMuPDF:Python中的强大PDF处理库 背景:为何选择PyMuPDF 在数字化时代,PDF文件因其跨平台的兼容性和对格式的严格保持而成为文档交换的通用格式。然而,处理PDF文件往往需要专门的工具或库。这就是PyMuPDF库的用武之地。PyMuP…...
天润融通AI技术助力汽车行业销售革新,邀约到店率翻倍增长
2024年汽车行业增速放缓,市场竞争加剧。在这种背景下,人工智能的加速渗透,各大汽车厂商纷纷引入大模型技术,对传统营销方式进行升级改造,寻找新的增长空间。 一直以来,汽车厂商投入大量预算,对…...
ubuntu安装mysql8.0
文章目录 ubuntu版本安装修改密码取消root跳过密码验证 ubuntu版本 22.04 安装 更新软件包列表 sudo apt update安装 MySQL 8.0 服务器 sudo apt install mysql-server在安装过程中,系统可能会提示您设置 root 用户的密码,请务必牢记您设置的密码。…...
数字图像处理笔记(三) ---- 傅里叶变换的基本原理
系列文章目录 数字图像处理笔记(一)---- 图像数字化与显示 数字图像处理笔记(二)---- 像素加图像统计特征 数字图像处理笔记(三) ---- 傅里叶变换的基本原理 文章目录 系列文章目录前言一、傅里叶变换二、离散傅里叶变…...
Golang | Leetcode Golang题解之第268题丢失的数字
题目: 题解: func missingNumber(nums []int) int {n : len(nums)total : n * (n 1) / 2arrSum : 0for _, num : range nums {arrSum num}return total - arrSum }...
基于PLC的智能饲喂系统设计:开启现代养殖自动化新篇章
基于PLC的智能饲喂系统设计 本设计包括设计报告,任务书,模拟工程仿真。本设计的制作智能饲喂是现代物流系统的重要组成部分,是代替人工饲喂的可行性计划,由自动控制与管理系统、配料系统、送料系统、自动统计系统、触摸屏监控系统…...
HBuilderX + 极光推送踩坑实录:免费版为啥息屏收不到通知?手把手教你配置与避坑
HBuilderX与极光推送免费版避坑指南:破解息屏通知失效难题 早上八点,你的咖啡还没喝完,测试组的消息就炸开了锅——"昨晚推送的版本在息屏状态下根本收不到通知!"作为使用HBuilderX开发跨平台应用的团队,这个…...
二分查找/二分答案
0.前言二分算法(Binary Search),也叫折半查找,是一种在有序数据集合中高效查找目标值的算法。它通过不断将查找范围缩小一半,快速定位目标,时间复杂度为 O(logn),远优于线性查找的 O(n)。1.原理…...
基于STM32与ADC的锂电池电量监测系统设计
1. 锂电池电量监测为什么需要STM32和ADC? 做嵌入式开发的朋友应该都遇到过这样的需求:设备用锂电池供电,需要实时显示剩余电量。比如手持设备、智能家居控制器或者无人机,电量显示都是刚需功能。但锂电池的特性决定了直接测量电量…...
STM32智慧停车场系统设计与SQLite应用
基于STM32的智慧停车场管理系统设计与实现(SQLite版)1. 项目概述1.1 系统架构本智慧停车场管理系统采用分布式架构设计,由以下核心组件构成:下位机控制单元:STM32F103ZET6微控制器作为主控芯片感知层:OV772…...
Kali Linux 2026.1 发布 (2026 主题 BackTrack 模式) - 领先的渗透测试发行版
Kali Linux 2026.1 发布 (2026 主题 & BackTrack 模式) - 领先的渗透测试发行版 The most advanced Penetration Testing Distribution 请访问原文链接:https://sysin.org/blog/kali-linux/ 查看最新版。原创作品,转载请保留出处。 作者主页&…...
MediaPipe Holistic实战效果:一张照片生成全身骨骼图,效果超乎想象
MediaPipe Holistic实战效果:一张照片生成全身骨骼图,效果超乎想象 1. 引言:当AI遇见全身感知 想象一下,你只需要上传一张普通的全身照片,AI就能自动识别出你的面部表情、手势动作和身体姿态,并生成一张精…...
隐私保护方案:OpenClaw+GLM-4.7-Flash本地化处理敏感数据
隐私保护方案:OpenClawGLM-4.7-Flash本地化处理敏感数据 1. 为什么需要本地化处理敏感数据? 去年我帮一位做财务咨询的朋友处理季度报表时,遇到了一个棘手问题。他需要分析上百份包含客户银行流水、身份证号等信息的Excel文件,但…...
TranslucentTB深度解析:如何用5MB内存实现Windows任务栏的视觉革命
TranslucentTB深度解析:如何用5MB内存实现Windows任务栏的视觉革命 【免费下载链接】TranslucentTB A lightweight utility that makes the Windows taskbar translucent/transparent. 项目地址: https://gitcode.com/gh_mirrors/tr/TranslucentTB 在Windows…...
从 POST 到落库回写:彻底讲透 SAP Gateway 中 Create Operation 的实现
在经典的 SAP Gateway 开发里,Create Operation 看上去只是一次新增动作,真正落到运行时,却牵涉到一条非常完整的链路:客户端发起 HTTP POST 请求,请求体里的 OData 数据被 Gateway 运行时反序列化成 ABAP 结构,开发者在对应的 <Entity Set>_CREATE_ENTITY 方法里接…...
