Reputation: 159
New to Vue and frameworks in general, and may have my thinking not very "Vue-like".
Trying to make a "super" button component that takes a prop, which dictates the buttons behavior so I only have to maintain one button component. The ideal form when implementing would like something like this...
<super-button isType="string"></super-button>
The template is...
<button class="buttonLow" v-bind:class="{buttonHigh: isSelected}">
<slot></slot>
</button>
Where isType
prop could be momentary
momentary-multi
toggle
or toggle-multi
.
I have a basic set of event emitters/methods and listeners that work regardless of the isType
and simply makes the buttons state high or low / on or off using another prop isSelected
.
The problem is trying to conditionally setup the mouse events depending on the isType
. While figuring out the logic, I used the @
syntax to setup the mouse events @click
@mousedown
@mouseup
etc. and everything worked great by itself. For example, the events for a momentary
button during testing looked like this...
<button @mousedown="emitButtonHigh()" @mouseup="emitButtonLow" @mouseleave="emitButonLow"></button>
However, a simple toggle button looked more like this...
<button @click="emitButtonToggle()"></button>
Obviously there is a bit of conflict there.
My attempted work around was to use a switch statement in created()
that would take isType
as the expression and conditionally register the appropriate mouse events...
created(){
switch(this.isType){
case ("momentary"):{
//attach on events
break;
}
case ("toggle"):{
//attach on events
break;
}
case ("toggle-multi"):{
//attach on events
break;
}
default:{
break;
}
}
}
While switch itself is working, I can't figure out how to attach the mouse events in this context. I can attach a custom event no problem using...
this.$root.$on('my-custom-event', ()=>{
//do stuff
});
but trying do something like...
this.$root.$on('click', ()=>{
//do stuff
});
or...
this.$on('click', ()=>{
//do stuff
});
Does not work, nor can I figure out any way to write it out that creates the same functionality as @click
let alone @mousedown
@mouseup
or other built-in events.
TL;DR
How do you write out the @
syntax or v-on
syntax, for built-in events (click, mousedown, mouseup, etc.), using $on
syntax, so the events actually fire?
Upvotes: 3
Views: 4918
Reputation: 9200
You could attach all these component events on a single handler, determine the event.type
s as they're fired and emit your custom events from here, while optionally passing additional arguments.
const SuperButton = Vue.extend({
template: `
<button
@mousedown="emitCustomEvent"
@mouseup="emitCustomEvent"
@mouseleave="emitCustomEvent">
<slot></slot>
</button>
`,
props: {
isType: {
type: String,
default:
String
},
// ...
},
methods: {
emitCustomEvent(e) {
let type = e.type.substr('mouse'.length);
let args = {
type,
isSelected: type === 'down',
args: {
// Your additional args here
}
};
switch(this.isType) {
case ("momentary"):{
//attach on events
break;
}
// ...
}
// Or emit events regardless of the "isType"
this.$emit(`mouse:${type}`, args);
this.$emit('mouse', args);
}
}
});
new Vue({
el: '#app',
methods: {
mousing(args) {
console.log(`mouse:${args.type} from component.`);
},
mouseLeaving() {
console.log('Mouse leaving.');
}
},
components: {
SuperButton
}
});
Vue.config.devtools = false;
Vue.config.productionTip = false;
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<super-button @mouse="mousing">Super button</super-button>
<super-button @mouse:leave="mouseLeaving">Super button 2, detecting leaving only</super-button>
</div>
Upvotes: 1