vue3中使用simple-keyboard实现虚拟键盘(带中文切换数字键盘)
效果图

官网
simple-keyboard官网:https://hodgef.com/simple-keyboard/ 打不开的话请用魔法
不足
中文语言包支持度不够。不过自己可以找语言包替换
依赖安装
npm install simple-keyboard --save
npm install simple-keyboard-layouts --save // 中文语言包
组件代码
<template>
<el-input ref="inputRef" v-model="model" @focus="focusInput" @keyup.enter="handleEnter" v-bind="$attrs">
<template v-for="(item, index) in $slots" :key="index" #[index]>
<slot :name="index"></slot>
</template>
</el-input>
<el-popover
:visible="visible"
:virtual-ref="inputRef"
virtual-triggering
placement="bottom"
:width="width"
:show-arrow="false"
:hide-after="0"
popper-style="padding: 0px;color:#000"
:persistent="false"
popper-class="keyboard-popper"
@after-leave="afterLeave"
@after-enter="afterEnter"
>
<div v-if="visible" class="simple-keyboard"></div>
</el-popover>
</template>
<script setup lang="ts">
import Keyboard from 'simple-keyboard'
import 'simple-keyboard/build/css/index.css'
import layout from 'simple-keyboard-layouts/build/layouts/chinese.js'
defineOptions({
inheritAttrs: false
})
const model = defineModel<string>()
const emits = defineEmits(['onChange', 'enter', 'close', 'focus'])
const props = defineProps({
layoutName: {
type: String,
default: 'default'
},
// 保留几位小数 layoutName为number时生效
precision: {
type: Number,
default: 2
},
// 获取焦点打开键盘
isOpen: {
type: Boolean,
default: true
}
})
const keyboard = ref<any>(null)
const visible = ref(false)
const inputRef = ref()
const width = ref(1000)
if (props.layoutName == 'number') width.value = 300
const displayDefault = ref({
'{bksp}': 'backspace',
'{lock}': 'caps',
'{enter}': 'enter',
'{tab}': 'tab',
'{shift}': 'shift',
'{change}': 'en',
'{space}': 'space',
'{clear}': '清空',
'{close}': '关闭',
'{arrowleft}': '←',
'{arrowright}': '→'
})
const open = () => {
if (visible.value) return
inputRef.value.focus()
emits('focus')
visible.value = true
}
const focusInput = () => {
if (visible.value) return
emits('focus')
if (props.isOpen) visible.value = true
}
const afterEnter = () => {
// 存在上一个实例时移除元素
const prevKeyboard = document.querySelectorAll('.init-keyboard')
if (prevKeyboard.length > 0) prevKeyboard[0]?.remove()
keyboard.value = new Keyboard('simple-keyboard', {
onChange: onChange,
onKeyPress: onKeyPress,
onInit: onInit,
layout: {
// 默认布局
default: [
'` 1 2 3 4 5 6 7 8 9 0 - = {bksp}',
'{tab} q w e r t y u i o p [ ] \\',
"{lock} a s d f g h j k l ; ' {enter}",
'{change} z x c v b n m , . / {clear}',
'{arrowleft} {arrowright} {space} {close}'
],
// 大小写
shift: [
'~ ! @ # $ % ^ & * ( ) _ + {bksp}',
'{tab} Q W E R T Y U I O P { } |',
'{lock} A S D F G H J K L : " {enter}',
'{change} Z X C V B N M < > ? {clear}',
'{arrowleft} {arrowright} {space} {close}'
],
// 数字布局
number: ['7 8 9', '4 5 6', '1 2 3', '. 0 {bksp}', '{arrowleft} {arrowright} {clear} {close}']
},
layoutName: props.layoutName,
display: displayDefault.value,
theme: 'hg-theme-default init-keyboard' // 添加自定义class处理清空逻辑
})
}
const afterLeave = () => {
displayDefault.value['{change}'] = 'en'
document.removeEventListener('click', handlePopClose)
}
const onInit = (keyboard: any) => {
keyboard.setInput(model.value)
keyboard.setCaretPosition(inputRef.value?.ref.selectionEnd)
document.addEventListener('click', handlePopClose)
}
const onChange = (input: any) => {
model.value = input
emits('onChange', input)
}
const onKeyPress = (button: any) => {
if (button !== '{close}') handleFocus()
if (button === '{lock}') return handleLock()
if (button === '{change}') return handleChange()
if (button === '{clear}') return handleClear()
if (button === '{enter}') return handleEnter()
if (button === '{close}') return handleClose()
if (button === '{arrowleft}') return handleArrow(0)
if (button === '{arrowright}') return handleArrow(1)
}
const handleLock = () => {
let currentLayout = keyboard.value.options.layoutName
let shiftToggle = currentLayout === 'default' ? 'shift' : 'default'
keyboard.value.setOptions({
layoutName: shiftToggle
})
}
const handleChange = () => {
let layoutCandidates = keyboard.value.options.layoutCandidates
// 切换中英文输入法
if (layoutCandidates != null && layoutCandidates != undefined) {
displayDefault.value['{change}'] = 'en'
keyboard.value.setOptions({
layoutName: 'default',
layoutCandidates: null,
display: displayDefault.value
})
} else {
displayDefault.value['{change}'] = 'cn'
keyboard.value.setOptions({
layoutName: 'default',
layoutCandidates: (layout as any).layoutCandidates,
display: displayDefault.value
})
}
}
const handleClear = () => {
keyboard.value.clearInput()
model.value = ''
}
const handleEnter = () => {
emits('enter')
}
const handleClose = () => {
visible.value = false
if (props.layoutName == 'number') {
// 处理精度
model.value = model.value?.replace(new RegExp(`(\\d+)\\.(\\d{${props.precision}}).*$`), '$1.$2').replace(/\.$/, '')
}
emits('close')
}
const handleArrow = (num: number) => {
// 处理左右箭头下标位置
const index = keyboard.value.getCaretPositionEnd()
if (num == 0 && index - 1 >= 0) {
keyboard.value.setCaretPosition(index - 1)
} else if (num == 1 && index + 1 <= (model.value?.length || 0)) {
keyboard.value.setCaretPosition(index + 1)
}
}
const handleFocus = () => {
// 处理焦点显示
setTimeout(() => {
const index = keyboard.value.getCaretPositionEnd()
inputRef.value.ref.selectionStart = inputRef.value.ref.selectionEnd = index
inputRef.value.focus()
}, 0)
}
const handlePopClose = (e: any) => {
// 虚拟键盘区域 输入框区域 中文选项区域
if (
(e.target as Element).closest('.keyboard-popper') ||
e.target == inputRef.value?.ref ||
/hg-candidate-box/.test(e.target.className)
) {
return
}
handleClose()
}
const close = () => {
handleClose()
}
defineExpose({ inputRef, visible, open, close })
</script>
<style>
.hg-theme-default .hg-button.hg-button-arrowleft,
.hg-theme-default .hg-button.hg-button-arrowright {
max-width: 70px;
}
.hg-theme-default .hg-button.hg-button-close {
max-width: 100px;
}
.hg-layout-number .hg-button.hg-button-close {
max-width: none;
}
.hg-layout-number .hg-button.hg-button-bksp {
max-width: 92px;
}
</style>
vue3中使用simple-keyboard实现虚拟键盘(带中文切换数字键盘)的更多相关文章
- (译)iPhone: 用公开API创建带小数点的数字键盘 (OS 3.0, OS 4.0)
(译)iPhone: 用公开API创建带小数点的数字键盘 (OS 3.0, OS 4.0) 更新:ios4.1现在已经将这个做到SDK了.你可以设置键盘类型为UIKeyboardTypeDecimal ...
- 一个数字键盘引发的血案——移动端H5输入框、光标、数字键盘全假套件实现
https://juejin.im/post/5a44c5eef265da432d2868f6 为啥要写假键盘? 还是输入框.光标全假的假键盘? 手机自带的不用非得写个假的,吃饱没事干吧? 装逼?炫技 ...
- VirtualBox中出现UUID have already exists ,并且数字键盘numlock效果相反
原文地址:https://www.cnblogs.com/xqzt/p/5053338.html 原因:由于linux密码登录错误,修改也报错误,所以只能重新安装虚拟机并在其中安装镜像文件,但是安装镜 ...
- 在Win7中IIS配置Asp.Net虚拟文件夹的方法及错误总结!
在Win7中IIS配置Asp.Net虚拟文件夹的方法总结! 一.右键[站点].点击[加入虚拟文件夹]或[虚拟应用程序],笔者建议最好建立虚拟应用程序,由于这就跟一个站点差点儿相同.不用考虑路径问题. ...
- rancher中级(二)(rancher中添加证书及操作虚拟主机)
制作一个ssl证书 首先了解关于ssl证书的背景知识:http://www.cnblogs.com/zxj015/p/4458066.html SSL证书包括: 1,CA证书,也叫根证书或者中间级证书 ...
- jQuery 虚拟数字键盘代码
先上效果: js直接应用: $('input').mynumkb(); 就出来效果 HTML: <input maxlength="4" type="tex ...
- vue3中使用axios如何去请求数据
在vue2中一般放在created中,但是在vue3中取消了created生命周期,请求方式有两种 直接在setup中去获取数据 setup(props) { const data = reactiv ...
- vue3中watch函数
watch 监听普通类型 let count = ref(1); const changeCount = () => { count.value+=1 }; watch(count, (newV ...
- 端午总结Vue3中computed和watch的使用
1使用计算属性 computed 实现按钮是否禁用 我们在有些业务场景的时候,需要将按钮禁用. 这个时候,我们需要使用(disabled)属性来实现. disabled的值是true表示禁用.fals ...
- vue 3 学习笔记 (七)——vue3 中 computed 新用法
vue3 中 的 computed 的使用,由于 vue3 兼容 vue2 的选项式API,所以可以直接使用 vue2的写法,这篇文章主要介绍 vue3 中 computed 的新用法,对比 vue2 ...
随机推荐
- NC224933 漂亮数
题目链接 题目 题目描述 小红定义一个数满足以下条件为"漂亮数": 该数不是素数. 该数可以分解为2个素数的乘积. 4 是漂亮数,因为 4=2*2 21 是漂亮数,因为 21=3* ...
- Buffer Queue原理
BufferQueue详解 原理一.BufferQueue 简介在工作中,我们经常会和Surface,ImageReader,ImageWriter BufferQueue打交道,它们之间是什么关系呢 ...
- Centos8 安装 MySQL8.0.26
下载 访问 https://dev.mysql.com/downloads/mysql/ 选择 Red Hat Enterprise Linux / Oracle Linux 选择 Red Hat E ...
- Spring Boot图书管理系统项目实战-4.基础信息管理
导航: pre: 3.用户登录 next:5.读者管理 只挑重点的讲,具体的请看项目源码. 1.项目源码 需要源码的朋友,请捐赠任意金额后留下邮箱发送:) 2.页面设计 出版社管理.语种管理.书架管 ...
- Redhat6更改yum源
最近虚拟机中安装了redhat6.3企业版,自带的yum用不起来,软件都找不到. 网上搜了一下说是没付钱...,需要改下yum源.操作步骤如下: 1.切换到yum源存放目录 [root@rhel6 ~ ...
- 一秒出图?SDXL-Turbo实时AI绘画整合包下载
SDXL Turbo是一种快速生成的AI构图模型,它基于一种称为对抗性扩散蒸馏的新训练方法,该方法允许在1到4个步骤中以高图像质量对大规模基础图像扩散模型进行采样,并将其与对抗性损失相结合,以确保即使 ...
- Alpine安装gcc g++ make编译环境
apk add gcc g++ make cmake gfortran libffi-dev openssl-dev libtool
- 【LeetCode链表#12】链表相交
链表相交 同:160.链表相交 力扣题目链接(opens new window) 给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点.如果两个链表没有交点,返 ...
- 第126篇: 异步函数(async和await)
好家伙,本篇为<JS高级程序设计>第十章"期约与异步函数"学习笔记 ES8 的 async/await 旨在解决利用异步结构组织代码的问题. 为为此增加了两个新关键 ...
- 一次kafka消息丢失问题处理
背景&现象 生产微服务架构环境,kafka消息消费服务架构如下: 当服务B接口出现宕机或者B接口调用超时,kafka消息消费端服务A出现异常,异常发生后未执行手动提交offset操作.待服务B ...