1

I currently have something like this:

// Emit event:
<btn @click="$emit('saveJsonFile') />

// Catch event:
<Component @saveJsonFile="doSomething" />

However, I try to stay away from magic strings (events) and instead, I want to have a file with the name of events as constants.

Example:

// events.js
export const EV_SAVE_JSON_FILE = 'saveJsonFile'

And make it a global instance:

import * as EVENTS from './events.js'
Vue.prototype.$EV = EVENTS

Now I use it like this:

// Child
<btn @click="$emit($EV.EV_SAVE_JSON_FILE) />

But how to I use it on the parent? I am getting a Vue ESLint error stating that it is an invalid v-on: v:on directives dont support the modifier 'ev_save_json_file'.

// Error
<Component @[$EV.EV_SAVE_JSON_FILE]="doSomething" />

I also tried making the event constant in small caps <Component @[$ev.ev_save_json_file]="doSomething" />, but same behavior.

Help!

5
  • just as a thought to think about, but magic strings are less evil than making your components not self contained by introducing the events file as a dependency Commented Jan 26, 2021 at 3:55
  • I was actually thinking which one is better. But kind of decided against the magic strings because of the risk for typos (with the capitalization and all). Would you say that it is indeed better and more normal to use magic strings in this specific case vs having a file dependency? @KeithNicholas Commented Jan 26, 2021 at 3:59
  • @tao oops! Thanks for pointing that out. That's actually my error when typing here on StackOverflow. I changed the variables and examples for simplicity and there I got typos myself. I have already updated my post now. Thanks Commented Jan 26, 2021 at 4:05
  • having done vue for some number of years now, this has never been a problem. If you were going to do it, I'd export the events from the component file, but you may want to just use typescript and enums instead Commented Jan 26, 2021 at 4:06
  • On Stack Overflow you don't type code. You copy/paste it, to make sure you also copy the problem (in case it's a typo). Anyways, another problem i spotted is you have a skewed understanding of what constitutes a global property in Vue and how to access it. If you want $EV to be available in any component instance, you should provide it as a plugin. That's why it's undefined. Your method might work if you do it before you create the app, but afterwards, mutating the prototype won't affect your instance. Commented Jan 26, 2021 at 4:07

1 Answer 1

2

I don't think vue template can interpret dynamic v-on:xxx directive. However, you can achieve the same effect by using generic v-on directive to achieve what you described. Details here:

https://github.com/vuejs/vue/issues/4703

So these are the same:

<sample-component v-on:click="someHandler" />
<sample-component v-on="{ click: someHandler }" />

Back to your problem, your component can be rewritten like this:

<Component v-on="{ [$EV.EV_SAVE_JSON_FILE]: doSomething }" />
Sign up to request clarification or add additional context in comments.

1 Comment

This works! Although I agree that it isn't as straightforward as I imagined it to be. I will have to check which option I'll go with. Thank you so much for this!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.