I have the following Vue event handlers with contenteditable:
<div contentEditable="true"
v-on:keyup="changed($event, current, 0)"
v-on:paste="changed($event, current, 0)"
v-on:blur="changed($event, current, 0)"
v-on:delete="changed($event, current, 0)"
v-on:focused="changed($event, current, 0)"></div>
However, I have many places where I call the same code and the code is getting long and verbose. Is there a way to bine event handlers? Something like:
v-on:keyup:paste:blur:delete:focused
?
I have the following Vue event handlers with contenteditable:
<div contentEditable="true"
v-on:keyup="changed($event, current, 0)"
v-on:paste="changed($event, current, 0)"
v-on:blur="changed($event, current, 0)"
v-on:delete="changed($event, current, 0)"
v-on:focused="changed($event, current, 0)"></div>
However, I have many places where I call the same code and the code is getting long and verbose. Is there a way to bine event handlers? Something like:
v-on:keyup:paste:blur:delete:focused
?
4 Answers
Reset to default 5You can create your custom directive for this purpose. This sample may help you:
Vue.directive('wrap-on', {
bind: function(el, binding, vnode) {
// Keep function to remove the event later.
el.wrappedEventFunctions = el.wrappedEventFunctions || {};
el.wrappedEventFunctions[binding.rawName] = binding.value;
for (var key in binding.modifiers) {
// Check if element is a vue ponent
if (vnode.ponentInstance) {
vnode.ponentInstance.$on(key, binding.value);
} else {
el.addEventListener(key, binding.value);
}
}
},
unbind: function(el, binding, vnode) {
for (var key in binding.modifiers) {
if (vnode.ponentInstance) {
vnode.ponentInstance.$off(key, el.wrappedEventFunctions[binding.rawName]);
} else {
el.removeEventListener(key, el.wrappedEventFunctions[binding.rawName]);
}
}
}
})
This directive will add event handlers to the element. It checks if the element is a vue ponent; if it is a vue ponent it registers the events via $on
. If it is not a vue ponent it uses addEventListener
. You can change this behavior if you want.
And usage is like:
<input v-wrap-on.click.keydown="mixedCallback" />
Or:
<some-custom-ponent v-wrap-on.click.keydown="mixedCallback">
...
</some-custom-ponent>
I don't think that there is a way, currently, to bine event listeners like you're describing.
What you could do is make this div it's own wrapper ponent (named 'editable-wrapper', for example) and emit one change
event:
<div
contentEditable="true"
v-on:keyup="$emit('change', {$event, current} )"
v-on:paste="$emit('change', {$event, current} )"
v-on:blur="$emit('change', {$event, current} )"
v-on:delete="$emit('change', {$event, current} )"
v-on:focused="$emit('change', {$event, current} )">
</div>
And then you would only need to listen to one change event on the ponent (data
is an object with $event
, and current
properties):
<editable-wrapper @change="changed(data)"></editable-wrapper>
We can declare events and event handlers like object and use v-on. In your case you declare this object in the mixin and use the same in all the templates.
let eventMixin = {
data() {
return {
events : {
'keyup' : 'changed($event, current, 0)',
'focus' : 'changed($event, current, 0)',
}
}
}
let ponent = {
mixins: [eventMixin],
template: '<div contentEditable="true" v-on=events ></div>
}
Hope this has helped . Vue v-on documentation you can find here, in which they have explained how to pass multiple events as object
It might be a case that you actually need something else. I think you can use watch
functionality, and it also handles "paste" and "cut" events (with mouse) and keyboard keys.
All you need is to set watcher to your property like so
data: {
coupon_code: '',
},
watch: {
coupon_code: function(){
console.log('watch-'+this.coupon_code);
},
},
and HTML
<input type="text" autoplete='off' v-model="coupon_code" >
documenation