Listen to custom event in Vue.js

Vue.js works great with browser events like click or mousedown . But does not work at all with custom events. Here is the code:

HTML:

 <div id="app" style="display: none" v-show="true"> <div v-el:ping v-on:ping="ping"> <div> <button v-on:click="click">Click</button> </div> </div> </div> 

JavaScript:

 new Vue({ el: '#app', data: { }, methods: { ping: function (event) { console.log('Vue ping', event); alert('Vue ping'); }, click: function (event) { jQuery(event.target).trigger('ping'); } }, ready: function () { console.log(this.$els); jQuery(this.$els.ping).on('ping', function (event) { console.log('jQuery ping', event); alert('jQuery ping'); }); } }); 

I am expecting alerts with Vue ping and jQuery ping . But only the latter pop up.

Codepen

+5
source share
3 answers

Vue has its own internal system for custom events , which you should use instead of jQuery / native DOM events:

 click: function (event) { // jQuery(event.target).trigger('ping'); this.$dispatch('ping', event.target) // send event up the parent chain, optionally send along a reference to the element. // or: this.$emit('ping') // trigger event on the current instance } 

Edit: $ dispatch for communication between parents and children. It seems you want to fire a custom event from the same component. In this case, you can simply call the method instead.

If you still want to listen to a custom event inside the same component, you:

  • want to use $ emit
  • cannnot use v-on:custom-event-name in the template (which will be used only for components). Rather, add an event method to events: ::

    events: {ping: function () {....}}

+6
source

Here it is in JS Vanilla:

HTML:

 <div id="app"> <div v-el:ping> <div> <button v-on:click="click">Click</button> </div> </div> </div> 

JS:

 (function() { new Vue({ el: '#app', data: { event: null }, methods: { ping: function(event) { alert('Vue ping'); }, click: function(event) { this.$els.ping.dispatchEvent(this.event); } }, ready: function() { this.event = document.createEvent("HTMLEvents"); this.event.initEvent("ping", true, true); this.$els.ping.addEventListener('ping', this.ping); } }); })(); 

pen: http://codepen.io/anon/pen/wGdvaV?editors=1010#0

+1
source

You should avoid mixing dom events and related components, as these are different levels of abstraction.

In any case, if you still want to do this, I think you need to cache this.el inside an instance of the vue component or take it using a computed property such as

 { computed : { jqueryEl(){ return $(this.el) } } } 

And then this.jqueryEl.trigger('ping') jQuery custom events this.jqueryEl.trigger('ping') .

Be sure to follow the rules for binding elements! For example, you can bind jQuery events dynamically (and also disable the destroy component!) As follows:

  ready : function(){ jQuery('body').on('ping.namespace', '[data-jquery="ping"]', function(){ ... }) }, destroy : function(){ jQuery('body').off('ping.namespace') } 

And don't forget to add the [data-jquery="ping"] attribute to the element that you want to respond to the ping event.

We hope that this information will help you achieve the expected result.

+1
source

Source: https://habr.com/ru/post/1245561/


All Articles