vue num-keyboard桌面端键盘组件
electron+element+vue 使用自定义键盘
网上找了很多,好像都不是很适用.所以自己撸了一个自定义键盘组件,记下来一是怕自己忘记,二是分享给同样需要的小伙伴
组件: components=>mi-keyboard
1 /** 2 * <mi-keyboard 3 v-if="keyboardShow" 4 :in="prd[activeKey] || 0" 5 @num_back="numBack" 6 @enter="keyConfirm" 7 @esc="escKeyboard" 8 ></mi-keyboard> 9 * keyboardShow 控制组件隐藏/显示 (需要控制隐藏/显示来注册对应的键盘事件) 10 * in 入参 11 * num_back 出参(方法) 12 * enter 键盘 enter 键返回 13 * esc 键盘 esc 键返回 (返回值为初始值,请在使用页面保存) 14 * 15 <el-input v-model="prd.off" @input="checkOff" :autocomplete="false" 16 @focus="showKeyBoard('off')" 17 :class="activeKey==='off'?'is-active off':'off'" // (is_active) 选中边框加颜色区别 18 :readonly="true" 19 > 20 <template slot="append"> 21 <span v-text="'%'"></span> 22 </template> 23 </el-input> 24 25 26 // 点击展示输入键盘 27 showKeyBoard(e) { 28 this.activeKey = e 29 this.keyboardShow = true 30 // 移除input的聚焦 31 document.querySelector('.' + e + ' > input').blur() 32 }, 33 // 键盘输入返回 34 numBack(e) { 35 console.log(e) 36 this.prd[this.activeKey] = e 37 }, 38 // 确认关闭键盘 39 keyConfirm() { 40 this.activeKey = '' 41 this.height = 45 42 this.keyboardShow = false 43 }, 44 // 取消键盘录入 45 escKeyboard() { 46 this.prd[this.activeKey] = this.oldNum 47 this.oldNum = 0 48 this.activeKey = '' 49 this.keyboardShow = false 50 }, 51 */ 52 Vue.component('mi-keyboard', { 53 props: [ 54 'in' 55 ], 56 data: function () { 57 return { 58 name: 'mi-keyboard', 59 _title: 'default', 60 keys: [ 61 '1', '2', '3', '4', '5', '6', '7', '8', '9', '00', '0', '.' 62 ], 63 } 64 }, 65 methods: { 66 // 确定 67 handleConfirm() { 68 this.$emit('enter', null) 69 }, 70 // 删除 71 back() { 72 const oldNum = this.in 73 const backNum = refundNumber(oldNum, 10) 74 this.$emit('num_back', backNum) 75 }, 76 // 清空 77 del() { 78 this.$emit('num_back', 0) 79 }, 80 // 点击数字输入 81 numbs(e) { 82 const oldNum = this.in 83 const newNum = determineDecimal(e) 84 this.backNum(oldNum, newNum) 85 }, 86 // 返回 87 backNum(oldNum, newNum) { 88 let backNum = Modifycomputer(oldNum, newNum) 89 backNum = determineDecimal(backNum) 90 this.$emit('num_back', backNum) 91 }, 92 }, 93 created: function () { 94 Keyset.Active(this.name); 95 this._title = !isUndefined(this.title) ? this.title : '' 96 }, 97 98 mounted: function () { 99 Keyset.Bind('esc', this.name, e => { 100 this.$emit('esc', this.in) 101 }) 102 Keyset.Bind('enter', this.name, e => { 103 this.$emit('enter', this.in) 104 }) 105 Keyset.Bind('backspace', this.name, e => { 106 this.back() 107 }) 108 Keyset.Bind('del', this.name, e => { 109 this.del() 110 }) 111 const numArr = this.keys 112 numArr.map(key => { 113 Keyset.Bind(key, this.name, e => { 114 this.numbs(key) 115 }) 116 }) 117 118 }, 119 destroyed: function () { 120 Keyset.Unactive('esc', this.name) 121 Keyset.Unactive('enter', this.name) 122 Keyset.Unactive('del', this.name) 123 Keyset.Unactive('backspace', this.name) 124 const numArr = this.keys 125 numArr.map(key => { 126 Keyset.Unactive(key, this.name) 127 }) 128 }, 129 template: ` 130 <div class="bottom-esc_btn"> 131 <div class="esc-btn_li"> 132 <div @click="numbs(item)" v-for="item in keys" v-text="item"></div> 133 </div> 134 <div class="esc-btn_lis"> 135 <ul> 136 <li @click="back">X</li> 137 <li @click="del">清除</br>Delete</li> 138 <li @click="handleConfirm">确定 Enter</li> 139 </ul> 140 </div> 141 </div> 142 ` 143 });
css: 这里是我们新来的实习生写的,自己懒得改了. 觉得不好看的勿喷
1 .bottom-esc_btn { 2 width: 100%; 3 display: flex; 4 margin-top: 20px; 5 } 6 .esc-btn_li { 7 width: 80%; 8 display: flex; 9 flex-wrap: wrap; 10 } 11 12 .esc-btn_li div:active, 13 .esc-btn_lis li:nth-child(1):active { 14 background: #5aa7ee; 15 } 16 17 .esc-btn_li div { 18 font-size: 15px; 19 margin: 0 8px 8px 0; 20 line-height: 60px; 21 width: 30%; 22 height: 60px; 23 background: #efeff4; 24 text-align: center; 25 } 26 27 .esc-btn_lis { 28 width: 20%; 29 } 30 31 .esc-btn_lis li:nth-child(1) { 32 width: 100%; 33 background: #ffc168; 34 height: 60px; 35 margin-bottom: 8px; 36 text-align: center; 37 padding: 6px 0 0 0; 38 } 39 40 .esc-btn_lis li:nth-child(2) { 41 width: 100%; 42 background: #efeff4; 43 height: 60px; 44 margin-bottom: 8px; 45 text-align: center; 46 font-size: 15px; 47 line-height: 26px; 48 } 49 50 .esc-btn_lis li:nth-child(3) { 51 width: 100%; 52 background: #1890ff; 53 height: 128px; 54 text-align: center; 55 font-size: 15px; 56 line-height: 117px; 57 } 58 59 .hand { 60 cursor: pointer; 61 }
外部js:
1. 键盘事件
1 // 键盘事件绑定处理,目前只支持一个模块里,一个键只执行最后一个绑定 2 /** 3 * 4 * 全局定义 5 Keyset.Bind("up", e => { 6 console.log(e,this); 7 }); 8 Keyset.Once("down", e => { 9 console.log(e,this); 10 }); 11 模块定义 12 Keyset.Bind("esc", "login", e => { 13 console.loge; 14 }); 15 */ 16 const Keyset = { 17 map: {}, 18 modules: [], 19 callback: function (e, m) { 20 if (isObject(m)) { 21 const cb = m.callback; 22 const cp = m.option; 23 const oc = m.once; 24 if (isFunction(cb)) cb(e, cp); 25 if (oc) { 26 m.callback = undefined; 27 } 28 } 29 }, 30 func: function (key) { 31 return e => { 32 const m = window._activeModule; 33 if (!isUndefined(this.map[key])) { 34 if (!isUndefined(this.map[key][m])) { 35 this.callback(e, this.map[key][m]); 36 } 37 if (!isUndefined(this.map[key]["$"])) { 38 this.callback(e, this.map[key]["$"]); 39 } 40 } 41 }; 42 }, 43 Active: function (module) { 44 window._activeModule = module; 45 this.modules.push(module); 46 }, 47 // leo 20210827 48 Unactive: function (key, module) { 49 const pos = this.modules.findIndex(res => res === module) 50 if (pos === -1) return; 51 if (pos > 0) { 52 this.modules = this.modules.filter((res, idx) => idx < pos); 53 window._activeModule = this.modules[pos - 1]; 54 } else { 55 window._activeModule = '$_'; 56 this.modules = []; 57 } 58 this.Unbind(key, module); 59 }, 60 // 可反复执行 61 Bind: function (key, module, callback, option) { 62 if (isFunction(module)) { 63 option = callback; 64 callback = module; 65 module = "$"; 66 } 67 if (isUndefined(this.map[key])) { 68 this.map[key] = {}; 69 Mousetrap.bind(key, this.func(key)); 70 } 71 this.map[key][module] = { 72 callback, 73 option, 74 }; 75 }, 76 //只会执行一次 77 Once: function (key, module, callback, option) { 78 if (isFunction(module)) { 79 option = callback; 80 callback = module; 81 module = "$"; 82 } 83 if (isUndefined(this.map[key])) { 84 this.map[key] = {}; 85 Mousetrap.bind(key, this.func(key)); 86 } 87 this.map[key][module] = { 88 callback, 89 option, 90 once: true, 91 }; 92 }, 93 // 取消息 94 Unbind: function (key, module) { 95 if (!isUndefined(this.map[key])) { 96 if (!isUndefined(this.map[key][module])) { 97 this.map[key][module] = undefined; 98 } 99 } 100 }, 101 };
2.数字处理方法
1 // 去掉第一位的0或者., 2 const firstCharacter = value => { 3 value = value.toString(); 4 if (value.length > 1) { 5 while ((value.charAt(0) == '0' && value.charAt(1) != '.') || value.charAt(0) == '.') { 6 value = value.substring(1, value.length); 7 } 8 9 } else { 10 value = value; 11 } 12 return value; 13 } 14 const determineDecimal = (value) => { 15 16 value = value.toString(); 17 // 判断刚开始是不是0开头的小数 18 if (value.charAt(0) == '0' && value.charAt(1) == '.' && value.charAt(2) != '.') { 19 value = value; 20 } else { 21 value = firstCharacter(value); 22 } 23 return value; 24 } 25 // 判断是不是多次输入‘.’,没有就正常加入 26 const Modifycomputer = (value, val) => { 27 // if(val!='.' || val != '00' || val != '0' ){ 28 // val=num_multiply(val,10000) 29 // } 30 // value = num_multiply(value + val,10000); 31 value = value.toString(); 32 val = val.toString(); 33 value = value + val; 34 let nums = 0; 35 for (let idx = 0; idx < value.length; idx++) { 36 if (value[idx] == '.') { 37 nums = nums + 1; 38 } 39 } 40 if (nums > 1) { 41 value = value.substring(0, value.length - 1); 42 } 43 return value; 44 } 45 // 退货退款的计算器页面清除最后一位 46 const refundNumber = (value, val) => { 47 value = value.toString(); 48 if (Number(val) === 10) { 49 if (value.length == 1) { 50 value = 0; 51 } else { 52 value = value.substring(0, value.length - 1); 53 } 54 } else { 55 value = value + val; 56 } 57 58 return value 59 }
使用方式写到组件中...