Vue.js works great with browser events such as click
or mousedown
. But 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 expect alert with Vue ping
and jQuery ping
. But only the later pops up.
CodePen
Here it is in vanilla JS:
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
You should avoid to mix a dom events and vue-components related ones because it's a different layers of abstraction.
Anyway, if you still want to do that, I think you need to cache this.el inside a vue-component instance or take it via computed-property like this
{
computed : {
jqueryEl(){ return $(this.el) }
}
}
And then trigger a custom jQuery events by this.jqueryEl.trigger('ping')
.
Sure to properly take care of keep the element's bindings up to date! For example you can bind jQuery events dynamically (and also unbind on component destroy!) like this:
ready : function(){
jQuery('body').on('ping.namespace', '[data-jquery="ping"]', function(){ ... })
},
destroy : function(){
jQuery('body').off('ping.namespace')
}
And don't forget to add attribute [data-jquery="ping"]
to an element which you would like to response a ping event.
Hope this information helps you to achieve the expected result.
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 is for parent-child communication, You seem to want to trigger a custom event from within the same comonent. In that case, you could instead simply call a method.
If you still want to listen to a custom event inside the same component, you:
want to use $emit
cannot use v-on:custom-event-name
in the template (that's only to be used on components). Rather, add the event method to the events:
:
events: { ping: function() {....} }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With