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>