携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第九天,点击查看活动详情.
今天工作中遇到这么一个需求
自己封装一个下图这样的键盘
我参考了网上的做法,但是过程中遇到了一些问题.
下面是他的步骤:
安装依赖
安装simpleKeyboard依赖:
npm install simple-keyboard --save
安装simpleKeyboard输入法依赖:
npm install simple-keyboard-layouts --save
虚拟键盘组件simpleKeyboard.vue
<style lang="less">
@deep: ~'>>>';
.hg-theme-default {
width: 70%;
.hg-button {
&.hg-red {
background: #db3e5d;
color: white;
&.close {
max-width: 200px;
}
}
&.change {
max-width: 200px;
}
}
}
</style>
输入框组件keyboard-input.vue
<template>
<div class="input-keyboard">
<el-input
v-model="inputValue"
:autofocus="autofocus"
:class="inputClass"
:suffix-icon="suffixIcon"
:type="type"
:show-password="showPassword"
:rows="rows"
:show-word-limit="showWordLimit"
:disabled="disabled"
:maxlength="maxlength"
:clearable="clearable"
:size="size"
:placeholder="placeholder"
@focus="focusInput($event)"
@input="inputFun"
>
<template v-if="appendPort" slot="append">[1-65535]</template></el-input
><SimpleKeyboard
:ref="keyboardClass"
:keyboardClass="keyboardClass"
@onChange="onChange"
@onKeyPress="onKeyPress"
:input="inputValue"
:maxLength="maxlength"
/>
</div>
</template>
<script>
import SimpleKeyboard from './simpleKeyboard.vue';
export default {
name: 'keyboard-input',
components: {
SimpleKeyboard,
},
props: {
keyboardClass: String,
autofocus: Boolean,
field: String,
value: {
default: '',
},
inputClass: String,
type: {
type: String,
default: 'text',
},
showPassword: {
type: Boolean,
default: false,
},
rows: Number,
showWordLimit: {
default: true,
},
disabled: {
type: Boolean,
default: false,
},
maxlength: Number,
clearable: {
type: Boolean,
default: true,
},
size: String,
placeholder: String,
appendPort: {
type: Boolean,
default: false,
},
autocomplete: {
default: '',
},
suffixIcon: {
default: '',
},
},
data() {
return {
input: null,
inputEle: null,
};
},
computed: {
inputValue: {
get() {
return this.value;
},
set(value) {
this.$emit('inputChange', value, this.field);
},
},
},
methods: {
inputChange() {
this.$emit('inputChange');
},
inputFun() {
this.$emit('input');
},
focusInput(e) {
this.inputEle = e.srcElement;
// 关闭所有keyboard
let arr = document.querySelectorAll('.hg-theme-default');
arr.forEach((ele) => {
ele.style.visibility = 'hidden';
});
// 打开当前输入框的keyboard
let currentKeyborad = this.$refs[this.keyboardClass];
currentKeyborad.$el.style.visibility = 'visible';
this.$emit('focus');
},
onChange(input) {
this.inputValue = input;
// 解决当输入框为密码输入框时,切换显示/隐藏密码,光标在开头问题,注意:element-ui版本号需为2.15.2及以上
this.inputEle.focus();
},
onKeyPress(button) {
// console.log('onKeyPress', button);
},
},
};
</script>
<style lang="less" scoped>
@import 'style/less/var';
@deep: ~'>>>';
.input-keyboard {
@{deep}.hg-theme-default {
position: fixed;
left: 50%;
bottom: 20px;
transform: translate(-50%);
visibility: hidden;
margin-top: 20px;
z-index: 2000;
// 中文文字选择框
.hg-candidate-box {
position: static;
transform: translateY(0);
}
// 键盘
.hg-rows {
}
}
&.citc-search-input {
.el-input {
width: 100% !important;
}
}
// 密码输入框显示密码图标效果
@{deep}.el-input__inner[type='text'] + span .el-icon-view {
color: red;
}
}
</style>
<template>
<div class="login" @click="judgeCloseKeyboard">
<div class="form-card" id="form-card">
<div class="form-body">
<el-form :model="form" ref="form" :rules="rules" @submit.native.prevent>
<el-form-item prop="username">
<keyboard-input
keyboardClass="login-username" <== 注意:页面内有多个输入框时,每个输入框的keyboardClass必须是唯一的,才不会报错
field="username"
:value="form.username"
:maxlength="10"
clearable
@inputChange="formItemChange"
placeholder="用户名"
></keyboard-input>
</el-form-item>
<button
class="btn-login"
:disabled="loginDisabled"
@click.prevent="submit('form')"
>
{{ isSubmitting ? '登录中' : '登录' }}
</button>
</el-form>
</div>
</div>
</div>
</template>
<script>
import { KeyboardInput } from '../../components/keyboard-input';
import { keyboardInputMixin } from '@/util/mixins';
import { judgeCloseKeyboard } from '@/util/core';
export default {
components: { KeyboardInput, LoginDialog },
mixins: [keyboardInputMixin],
data() {
return {
judgeCloseKeyboard,
isSubmitting: false,
form: {
username: '',
},
rules: {
username: [
{ required: true, message: '请输入用户名', trigger: 'blur' },
],
},
};
},
computed: {
loginDisabled() {
return this.form.username === '' || this.isSubmitting;
},
},
methods: {
submit(formName) {
this.$refs[formName].validate((valid, errFields) => {
if (valid) {}
});
},
},
};
</script>
<style lang="less" scoped>
@deep: ~'>>>';
.login {
width: 100%;
height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
@{deep}.vue-touch-keyboard{
width: 600px;
}
}
.form-card {
width: 550px;
border-radius: 5px;
background: rgba(255, 255, 255, 0.8);
padding: 40px 120px 80px 120px;
box-sizing: border-box;
.btn-login {
width: 100%;
height: 40px;
background: #db3e5d;
border-radius: 2px;
border: none;
color: rgba(255, 255, 255, 1);
&:hover {
cursor: pointer;
}
&:focus {
outline: none;
}
&:disabled {
cursor: not-allowed;
background-color: rgba(219, 62, 93, 0.5);
}
}
}
@{deep}.el-form-item {
margin-bottom: 30px;
.el-input__inner {
padding: 0 16px;
font-size: 13px;
border-radius: 2px;
border-color: rgba(0, 0, 0, 0.15);
&:hover,
&:focus,
&.is-active {
border-color: #db3e5d;
}
}
}
</style>