VueJS Custom directive + emit event VueJS Custom directive + emit event vue.js vue.js

VueJS Custom directive + emit event


A <div> is not a VueComponent, which means it doesn't have an $emit method.

So to make your Vue custom directive emit an event, you will have to do some checking first:

  • If the directive was used in a Vue custom component, then call $emit() of that component's instance
  • If the directive was used in a regular DOM element (...because there's no $emit()...), then dispatch a native DOM event using .dispatchEvent.

Luckily, Vue's v-on listeners respond to native custom events.

That should be all. Demo implementation below.

Vue.component('my-comp', {  template: `<input value="click me and check the console" size="40">`});Vue.directive('my-directive', {  bind: function (el, binding, vnode) {    // say you want to execute your logic when the element is clicked    el.addEventListener('click', function (e) {          var eventName = 'my-event';      var eventData = {myData: 'stuff - ' + binding.expression}      if (vnode.componentInstance) {      	vnode.componentInstance.$emit(eventName, {detail: eventData}); // use {detail:} to be uniform      } else {      	vnode.elm.dispatchEvent(new CustomEvent(eventName, {detail: eventData}));      }    })  }})new Vue({  el: '#app',  methods: {    handleStuff(e) { console.log('my-event received', e.detail); }  }})
<script src="https://unpkg.com/vue@2.5.15/dist/vue.min.js"></script><div id="app">  <div v-my-directive.modifier="'native element'" @my-event="handleStuff">CLICK ME AND CHECK THE CONSOLE</div>  <hr>  <my-comp v-my-directive.modifier="'custom component'" @my-event="handleStuff"></my-comp></div>