动手实现获取并展示快捷键效果的Input组件

遇到一个需求,页面内要自定义快捷键,这就需要可以有地方设置和展示快捷键,找了一圈Element UI发现没有能稍微改改就能用的组件,所以自己动手写了一个。
这个只有快捷键展示功能,快捷键实际绑定生效的话是依赖传回的快捷键数据,由另外的组件处理的。目前只测试了Chrome的环境。

效果如下:
image

关键点

虽然看起来像是一个Input但在组件内实际上是展示一个标签效果,还需要有删除按钮。这就得在输入框内放下html代码,浏览器的Input组件显然不适合,这就只能自己仿一个类Input组件效果了。

focus、blur、选中高亮效果

Input这类组件是没有focusblur选中高亮效果这些效果的,还好浏览器有预留实现方式,网上也早已有网友提供方案,在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里会标记是否按下altctrl(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


01小径
在路上,遇见了一只BUG,我将它抓住,收藏在了这里。<( ̄︶ ̄)>
654 声望
15 粉丝
0 条评论
推荐阅读
Theia 开发环境搭建
Node.js >= 16.14.0 and < 17.If you are interested in Theia's VS Code Extension support then you should use a Node version at least compatible with the one included in the version of Electron ...

LnEoi2阅读 461

「多图预警」完美实现一个@功能
一天产品大大向 boss 汇报完研发成果和产品业绩产出,若有所思的走出来,劲直向我走过来,嘴角微微上扬。产品大大:boss 对我们的研发成果挺满意的,balabala...(内心 OS:不听,讲重点)产品大大:咱们的客服 I...

wuwhs39阅读 4.7k评论 5

封面图
安全地在前后端之间传输数据 - 「3」真的安全吗?
在「2」注册和登录示例中,我们通过非对称加密算法实现了浏览器和 Web 服务器之间的安全传输。看起来一切都很美好,但是危险就在哪里,有些人发现了,有些人嗅到了,更多人却浑然不知。就像是给门上了把好锁,还...

边城31阅读 7.1k评论 5

封面图
涨姿势了,有意思的气泡 Loading 效果
今日,群友提问,如何实现这么一个 Loading 效果:这个确实有点意思,但是这是 CSS 能够完成的?没错,这个效果中的核心气泡效果,其实借助 CSS 中的滤镜,能够比较轻松的实现,就是所需的元素可能多点。参考我们...

chokcoco19阅读 2k评论 2

在前端使用 JS 进行分类汇总
最近遇到一些同学在问 JS 中进行数据统计的问题。虽然数据统计一般会在数据库中进行,但是后端遇到需要使用程序来进行统计的情况也非常多。.NET 就为了对内存数据和数据库数据进行统一地数据处理,发明了 LINQ (L...

边城17阅读 1.9k

封面图
【已结束】SegmentFault 思否写作挑战赛!
SegmentFault 思否写作挑战赛 是思否社区新上线的系列社区活动在 2 月 8 日 正式面向社区所有用户开启;挑战赛中包含多个可供作者选择的热门技术方向,根据挑战难度分为多个等级,快来参与挑战,向更好的自己前进!

SegmentFault思否20阅读 5.6k评论 10

封面图
过滤/筛选树节点
又是树,是我跟树杠上了吗?—— 不,是树的问题太多了!🔗 相关文章推荐:使用递归遍历并转换树形数据(以 TypeScript 为例)从列表生成树 (JavaScript/TypeScript) 过滤和筛选是一个意思,都是 filter。对于列表来...

边城18阅读 7.6k评论 3

封面图
654 声望
15 粉丝
宣传栏