遇到一个需要,页面内要自定义快捷键,这就须要能够有中央设置和展现快捷键,找了一圈Element UI
发现没有能略微改改就能用的组件,所以本人入手写了一个。
这个只有快捷键展现性能,快捷键理论绑定失效的话是依赖传回的快捷键数据,由另外的组件解决的。目前只测试了Chrome
的环境。
成果如下:
关键点
尽管看起来像是一个Input
但在组件内实际上是展现一个标签
成果,还须要有删除按钮。这就得在输入框内放下html
代码,浏览器的Input
组件显然不适宜,这就只能本人仿一个类Input
组件成果了。
focus、blur、选中高亮成果
非Input
这类组件是没有focus
、blur
、选中高亮成果
这些成果的,还好浏览器有预留实现形式,网上也早已有网友提供计划,在div
里加上tabindex="0"
属性,就能让div
取得这些成果。
tabindex
属性规定了Tab
按键的程序,写0
的话是会按组件默认程序被选中的,如果写-1
则始终无奈被选中。因为自身是仿Input
组件模式,能被Tab
获取也刚好很正当。
而后加上CSS的获取焦点的边框成果、鼠标挪动到此显示文本类型指针
.shortcut-key-input { cursor: text; transition: border-color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);}.shortcut-key-input:focus { border-color: #188cff; box-shadow: 0 0 4px rgba(24, 140, 255, 0.38);}
文本提醒
当没有内容时须要跟Input
一样,能够默认显示文本提醒。这也是放一个div在外面,用Vue
管制,如果输入的标签变量有数据时,就不让此元素显示。
光标闪动成果
这个比拟好解决,在类Input
外面放一个伪元素,当获取焦点的时候增加此伪元素,而后再给此元素一个CSS3的动画,就有光标闪动的成果了。
@keyframes Blink { 0% { opacity: 0; } 100% { opacity: 1; }}.shortcut-key-input.cursor::after { content: "|"; animation: Blink 1.2s ease 0s infinite; font-size: 18px; position: absolute; top: 1px; left: 8px;}
按键捕捉
按键捕捉次要靠keydown
事件,其中传回的event
里会标记是否按下alt
、ctrl(control)
等信息,所以做组合按键依赖此信息就能够实现。
因为每次按键都会触发事件,所以要屏蔽掉功能键的事件。代码只实现了一个非功能键的组合,须要多功能键能够另外建设变量判断间断按键的状况而后解决。
handleKeydown(e) { const { altKey, ctrlKey, shiftKey, key, code } = e; if (!CODE_CONTROL.includes(key)) { if (!this.keyRange.includes(code)) return; let controlKey = ""; [ { key: altKey, text: "Alt" }, { key: ctrlKey, text: "Ctrl" }, { key: shiftKey, text: "Shift" } ].forEach(curKey => { if (curKey.key) { if (controlKey) controlKey += "+"; controlKey += curKey.text; } }); if (key) { if (controlKey) controlKey += "+"; controlKey += key.toUpperCase(); } this.addHotkey({ text: controlKey, controlKey: { altKey, ctrlKey, shiftKey, key, code } }); } e.preventDefault(); },
CODE_CONTROL
是另外预设的按键code
码汇合,不便解决。原本用的是keyCode
的,但keyCode
曾经被废除了,举荐的是code
。addHotkey
就是增加到相应变量的函数,其中次要出判断一下是否有反复的快捷键。
而后预留了一个内部验证的接口,为了多快捷键的时候能够判断是否有反复。
还有一个max
接口,能够限度每个组件的快捷键个数。
addHotkey(data) { if (this.list.length && this.list.some(item => data.text === item.text)) return; if (this.list.length && this.list.length.toString() === this.max.toString()) return; if (!this.verify(data)) return; this.list.push(data); }
在线预览
https://codesandbox.io/s/vue-hotkeyinput-90m2k