Search code examples
vue.jsevent-handlingconstants

Vue.js custom events from constants


I have a Vue.js component that publishes certain events.

<MyComponent @some-event="myHandler"/>

Inside the component you have something like

this.$emit('some-event', someData);

Pretty basic. But to make the code cleaner, it would be nice if I could have a the string 'some-event' defined in a constant somewhere and to be able to use it with $emit() and when declaring the the event handler. Something like this:

const EVENT_NAME = 'some-event';

this.emit(EVENT_NAME, someData);

<MyComponent @{{EVENT_NAME}}="myHandler"/>

I just made up the @{{EVENT_NAME}} syntax but hopefully the idea makes sense. Is this possible?


Solution

  • You can use Dynamic Arguments, e.g. (being event_name the constant):

    <MyComponent @[event_name]="myHandler" />
    

    but with some caveats:

    • There are several constraints to what you can use inside the [];
    • For the event_name constant to be used in the template, it must be accessible to the template, which means it should be a data property, a computed, or similar. It does not suffice to merely be declared in the script, outside of the vue component.
    • Attributes will be parsed as lowercase, so your constant must be event_name, not EVENT_NAME or Event_Name (you can even use those, but they will be treated as event_name; see how I declare the data below).

    Working demo:

    const EVENT_NAME = 'some-event';
    
    Vue.component(`my-component`, {
      template: `
        <button @click="myCompInternalHandler">click me to emit an event whose name is the value of event_name</button>
      `,
      methods: {
        myCompInternalHandler() {
          this.$emit(EVENT_NAME, {someData: 112233});
        }
      }
    });
    
    new Vue({
      el: '#app',
      data: {
        message: 'Hello Vue.js!',
        event_name: EVENT_NAME // key has to be lowercase, because it is used in the template as dynamic attr
      },
      methods: {
        myHandler(e) {
          console.log('received at parent:', e);
        }
      }
    })
    <script src="https://unpkg.com/vue"></script>
    
    <div id="app">
      <my-component @[event_name]="myHandler" />
      <p>{{ message }}</p>
    </div>