What does v-on="..." syntax mean in VueJS?
TLDR:
basic usage
<!-- object syntax (2.4.0+) --> <button v-on="{ mousedown: doThis, mouseup: doThat }"></button>]
So basically @click="..."
equals v-on:click="..."
equals v-on="{click:...}"
TLDR:
vuetify implementation:
genActivator () { const node = getSlot(this, 'activator', Object.assign(this.getValueProxy(), { on: this.genActivatorListeners(), attrs: this.genActivatorAttributes(), })) || [] this.activatorNode = node return node }
Some insight:
It is useful if you want to abstract components and pass down multiple listeners at once instead of writing multiple lines of assignments.
Consider a component:
export default { data() { return { on: { click: console.log, contextmenu: console.log }, value: "any key value pair" } }}
<template> <div> <slot name="activator" :on="on" :otherSlotPropName="value" > <defaultComponent v-on="on" /> </slot> </div></template>
Given the component above, you can access the slot properties and pass them into your custom component:
<ExampleComponent> <template v-slot:activator="{ on, otherSlotPropName }"> <v-btn color="red lighten-2" dark v-on="on" > Click Me </v-btn> </template> <ExampleComponent />
Somethimes its easier to see it in plain javascript:
Comparing the component from above - with render function instead of template:
export default { data() { return { on: { click: console.log, contextmenu: console.log }, value: "any key value pair" } }, render(h){ return h('div', [ this.$scopedSlots.activator && this.$scopedSlots.activator({ on: this.on, otherSlotPropName: this.value }) || h('defaultComponent', { listeners: this.on } ] }}
In the source:
In case of a blank v-on="eventsObject"
the method bindObjectListener
will be called resulting in the assignment of the events to data.on
.
This happens in the createComponent
scope.
Finaly the listeners
are passed as VNodeComponentOptions
and updated by updateListeners
.
Where Vue extends - the Vuetify implementation inspected:
When taking into account that one can join and extend vue instances, one can convince himself that any component can be reduced to a more atomic version.
This is what vuetify utilizes in the e.g. v-dialog
component by creating a activator mixin
.
For now one can trace down the content of on
mounted by the activatable
:
const simplyfiedActivable = { mounted(){ this.activatorElement = this.getActivator() }, watch{ activatorElement(){ // if is el? this.addActivatorEvents() } }, methods: { addActivatorEvents(){ this.listeners = this.genActivatorListeners() }, genActivatorListeners(){ return { click: ..., mouseenter: ..., mouseleave: ..., } },
genActivator () { const node = getSlot(this, 'activator', Object.assign(this.getValueProxy(), { on: this.genActivatorListeners(), attrs: this.genActivatorAttributes(), })) || [] this.activatorNode = node return node },
}}
With above snippet all there is left is to implement this into the actual component:
// vuetify usage/implemention of mixins const baseMixins = mixins( Activatable, ...other)const sympliefiedDialog = baseMixins.extend({ ...options, render(h){ const children = [] children.push(this.genActivator()) return h(root, ...options, children) }})