Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vuejs version of Hotkeys #115

Open
rutvij2292 opened this issue Oct 14, 2019 · 7 comments
Open

Vuejs version of Hotkeys #115

rutvij2292 opened this issue Oct 14, 2019 · 7 comments
Labels

Comments

@rutvij2292
Copy link

rutvij2292 commented Oct 14, 2019

Hello,

Thanks for a wonderful keyboard binding library, I was trying to integrate this library in my vue project I and can't.

Does any one tried to implement in their vuejs project? If someone tried, guide me how to integrate it, that would be amazing.

Thanks!
Rutvij

@jaywcjlove jaywcjlove pinned this issue Oct 14, 2019
@japorized
Copy link

japorized commented Dec 18, 2019

Mind sharing more about what you're trying to achieve? It would help if you can give us more insight into how deep do you want the lib to integrate with your project.

I'm currently using this lib in my project, but I'm not doing anything too complicated and it's just sitting on top of what I have. If that's what you want, feel free to check out the file where I'm using it.

Cheers!

@jennings
Copy link
Contributor

jennings commented Jan 16, 2020

You can use the hotkeys function directly to bind and unbind hotkeys. I made an example of using it with Vue on CodeSandbox, but essentially you can use the mounted and beforeDestroy methods to bind a hotkey whenever a component is mounted on the screen (this assumes there's only one instance of this component mounted at a time):

import hotkeys from "hotkeys-js";

export default {
  name: "ComponentWithHotkey",
  mounted() {
    hotkeys("a", () => this.hotkeyPressed());
  },
  beforeDestroy() {
    hotkeys.unbind("a");
  },
  methods: {
    hotkeyPressed() {
      this.$emit("increment");
    }
  }
};

@jaywcjlove jaywcjlove added the Demo label Mar 9, 2020
@scambier
Copy link

The problem is that the imported hotkeys is a singleton, so you have to manually unbind all the bindings you made on a given component (cf. @jennings example). If you don't, Hotkeys will hold onto a reference of your component; it won't be freed from memory, and you'll rebind the same keys when the component is mounted again. It will build up the memory, the CPU usage, and may introduce bugs.

Unfortunately, if re-binding the same keys on a new component doesn't introduce bugs, you'll have a memory leak that will be hard to track.

@jaywcjlove
A way to fix this would be to let users instantiate and manage their own Hotkeys instance(s) themselves, if that's possible. Or, without rewriting much, you could warn users if they're re-binding the same keys via a console.warn (maybe activated only via a debug flag to avoid spam)

@jennings
Copy link
Contributor

@scambier Even if you had a separate instance of the hotkeys object, you'd still need a clean-up step that gets called when the component is being unmounted. I'm not sure if having a separate instance of hotkeys would solve the resource leak.

// hypothetical API for creating a hotkeys instance
import { makeHotkeysInstance } from "hotkeys-js";

export default {
  name: "ComponentWithHotkey",
  mounted() {
    this.hotkeys = makeHotkeysInstance();
    this.hotkeys("a", () => this.hotkeyPressed());
  },
  beforeDestroy() {
    // still requires cleanup or else the arrow function
    // will remain bound to the window's keydown event
    this.hotkeys.destroy();
  },
  ...
};

@scambier
Copy link

You're right, I'm not sure what I had in mind. But your example shows a nice way to do it: you don't have to keep an up-to-date list of unbind() calls, as a single call to this.hotkeys.destroy() could do the job. That'd be cleaner and less error-prone IMO

@ghost
Copy link

ghost commented Jul 6, 2020

Sorry for responding to an old thread, but I took a different route by binding hotkeys to the Vue instance prototype. And only clean up using the scope functions in my components. This way the cleanup is simple and hotkeys is called only once.

Before calling new Vue() attach hotkeys: Vue.prototype.$keys = hotkeys.noConflict(true)

And in my components:

export default {
    data: {
        hotKeyScope: 'some-usefull-name'
    },
    created() {
         this.$keys('enter', this.hotKeyScope, () => { /*...*/ })
    },
    beforeDestroy() {
        this.$keys.deleteScope(this.hotKeyScope);
    }
}

I've not tested all use/edge-cases, but worked well enough in my apps. My guess is that if you have multiple competing scopes on the same page, you'll have to manage these yourself.

@jaywcjlove jaywcjlove unpinned this issue Aug 7, 2021
@Mitscherlich
Copy link

Hi there, I made a composition-api version of this and published as vue-use-hotkeys on npm. Try it out if interested.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

6 participants