在Vue.js中侦听div组件上的"esc"键事件

Che*_*hen 23 javascript event-handling vuejs2

我希望听一个'esc'键事件,以便调用Vue组件中的方法.文档显示了这个例子:

<input v-on:keyup.enter="submit">
Run Code Online (Sandbox Code Playgroud)

但我正在使用<div></div>,需要从外面捕捉事件.但是,我希望不要重载全局处理程序或类似的东西.

有什么建议?

laa*_*som 35

对于任何从谷歌到这里的人来说,在Vue 2 ...

<div @keydown.esc="something_in_your_methods"></div>
Run Code Online (Sandbox Code Playgroud)

  • _或者_如果您将 `tabindex` 添加到 `div`,如 `tabindex="0"` (8认同)
  • 如果您有一个嵌套元素可以像输入一样捕获击键,则这仅适用于放置在 div 上,在这种情况下,事件可能会冒泡。div 本身不会捕获事件。 (7认同)
  • 谢谢,解决问题,但只能在&lt;input&gt;或&lt;textarea&gt;上。 (3认同)
  • @MosheL 它对我来说适用于“&lt;div&gt;”。我使用的是 Vue 版本 2.5.17 (2认同)

Pie*_*NAY 18

主要元素上需要确定的三件事:

  • 它有一个选项卡索引
  • 它或后代是焦点
  • 它正在监听事件

以下是我通常管理模式的方式:

<div ref="modal" @keyup.esc="close" tabindex="-1">
   <!-- Modal content -->
</div>
Run Code Online (Sandbox Code Playgroud)
mounted() {
    this.$refs.modal.focus();
}
Run Code Online (Sandbox Code Playgroud)


Fri*_*ian 7

我所做的就是去混音。

名为close.js的文件中的mixin

export default {
    created() {
        let that = this;

        document.addEventListener('keyup', function (evt) {
            if (evt.keyCode === 27) {
                that.close();
            }
        });
    },
};
Run Code Online (Sandbox Code Playgroud)

导入并在所需组件中使用

import closeMixin from './../../mixins/close.js';

export default {
    mixins: [closeMixin],
    props: [],
    computed: {}
    methods: {
        close(){
            // closing logic
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 但是,您忘记在销毁时删除事件侦听器,这不会产生意想不到的影响吗? (8认同)
  • 截至 2022 年,`if (evt.key === "Escape") {` 是首选(未弃用)表达式。 (3认同)
  • 将其存储在变量中,例如`this.escListener = document.addEventListener('keyup'`,然后存储在destroy()生命周期方法`document.removeEventListener(this.escListener)`中 (2认同)

Mat*_*uya 7

就我而言,我创建了一个指令 v-esc.ts。(\xe2\x80\xbb 这是Vue3指令的写法)

\n
import { Directive } from \'vue\'\nconst directive: Directive = {\n  beforeMount(el, binding) {\n    el._keydownCallback = (event) => {\n        if (event.key === \'Escape\') {\n            binding.value()\n      }\n    }\n    document.addEventListener(\'keydown\', el._keydownCallback)\n  },\n  unmounted(el, binding) {\n    document.removeEventListener(\'keydown\', el._keydownCallback)\n    delete el._keydownCallback\n  }\n}\nexport const esc = { esc: directive }\n
Run Code Online (Sandbox Code Playgroud)\n

然后我可以在任何像这样的组件中使用它。\n(注意:您必须将函数参数传递给 v-esc,因为该参数在指令中作为 binding.value() 执行)

\n
<template>\n  <img\n    @click.prevent="close"\n    v-esc="close"\n    src="@/assets/icons/close.svg"\n  />\n</template>\n\n<script lang="ts">\nimport { defineComponent } from \'vue\'\nimport { esc } from \'@/common/directives/v-esc\'\nexport default defineComponent({\n  name: \'nitCloseButton\',\n  ...\n  methods: {\n    close() {\n      this.$emit(\'close\')\n    }\n  },\n  directives: {\n    ...esc\n  }\n})\n</script>\n
Run Code Online (Sandbox Code Playgroud)\n

PS\n一个月后,我还需要向左箭头和向右箭头键。\n因此,我使这个指令更加通用,如下所示。

\n
import { Directive } from \'vue\'\nconst directive: Directive = {\n  beforeMount(el, binding) {\n    el._keydownCallback = event => {\n      console.log(\'keydown\', event.key)\n      if (event.key === binding.arg) {\n        binding.value()\n      }\n    }\n    document.addEventListener(\'keydown\', el._keydownCallback)\n  },\n  unmounted(el, binding) {\n    document.removeEventListener(\'keydown\', el._keydownCallback)\n    delete el._keydownCallback\n  }\n}\nexport const keydown = { keydown: directive }\n
Run Code Online (Sandbox Code Playgroud)\n

您可以通过将键名作为 binding.args\n(v-keydown:{keyName} 如下所示) 传递来检测任何键的 keydown

\n
<button\n  v-keydown:ArrowLeft="moveToPreviousPage"\n  class="controller-button lo-center"\n  @click="moveToPreviousPage"\n>\n  <arrow-icon :rotation="180" />\n</button>\n<button\n  v-keydown:ArrowRight="moveToNextPage"\n  class="controller-button lo-center"\n  @click="moveToNextPage"\n\nexport default defineComponent({\n  name: \'componentName\',\n  directives: {\n    ...keydown\n  }\n...\n})\n
Run Code Online (Sandbox Code Playgroud)\n


Lau*_*Mat 5

你不能。按键事件从 body 标签发送,Vue 无法挂载到该<body>标签。

摘自《当 VueJS 无法帮助你时》]

您必须设置自己的事件侦听器。

(图片来源和更多信息,请参见当 VueJS 无法帮助您时

  • 然而你可以: `&lt;div @keydown.esc="something"&gt;` 工作得很好。 (5认同)

Bas*_*MHL 5

使keydown事件在div和其他不可聚焦元素上起作用的秘诀是添加一个tabindex属性:

<div tabindex="0"
    @keydown.left="previousImage"
    @keydown.right="nextImage" />
Run Code Online (Sandbox Code Playgroud)

现在,div已成为可聚焦的元素,并且将触发关键事件。

这是有关可聚焦元素和tabindex的更多信息

  • 这对可访问性来说不是有潜在的坏处吗? (2认同)