basic usage
<!-- object syntax (2.4.0+) -->
<button v-on="{ mousedown: doThis, mouseup: doThat }"></button>]
In a nutshell, @click="..."
is equivalent to v-on:click="..."
which is the same as v-on="{click:...}"
vuetify implementation:
genActivator () {
const node = getSlot(this, 'activator', Object.assign(this.getValueProxy(), {
on: this.genActivatorListeners(),
attrs: this.genActivatorAttributes(),
})) || []
this.activatorNode = node
return node
}
Insightful information:
This approach proves useful when abstracting components and passing multiple listeners at once instead of writing separate assignment lines.
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>
By using the component above, slot properties can be accessed and passed into custom components like so:
<ExampleComponent>
<template v-slot:activator="{ on, otherSlotPropName }">
<v-btn
color="red lighten-2"
dark
v-on="on"
>
Click Me
</v-btn>
</template>
<ExampleComponent />
Easier visualization with plain Javascript:
Comparing the previous component - utilizing render function rather than 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
}
]
}
}
Exploring the source code:
If a blank v-on="eventsObject"
argument is present, the method bindObjectListener
will be invoked to assign events to data.on
.
This process occurs within the createComponent
realm.
Subsequently, the listeners
are updated via updateListeners
as VNodeComponentOptions
.
Vue extension in Vuetify's context - an in-depth look into the implementation:
By merging and extending Vue instances, any component can be reduced into a more modular form.
Vuetify demonstrates this concept through components like v-dialog
by incorporating an activator mixin
.
Examining the content of on
mounted by the activatable
yields:
const simplyfiedActivable = {
mounted(){
this.activatorElement = this.getActivator()
},
watch{
activatorElement(){
// if el exists
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
},
}
}
To implement the above logic into an actual component, consider:
// Usage of Vuetify mixins for implementation
const baseMixins = mixins(
Activatable,
...other
)
const sympliefiedDialog = baseMixins.extend({
...options,
render(h){
const children = []
children.push(this.genActivator())
return h(root, ...options, children)
}
})