我遇到了v-dialog component的Vuetify示例,该示例具有一个称为activator的作用域插槽,定义如下:
<template v-slot:activator="{ on }">
<v-btn
color="red lighten-2"
dark
v-on="on"
>
Click Me
</v-btn>
</template>
我了解scoped slots from VueJS docs的目的和destructuring slot props的概念,但在此示例中我不了解v-on="on"
的含义。特别是当未使用v-on
指令指定事件时,这意味着什么?
VueJS docs on v-on
仅结合明确指定的事件名称(例如v-on:click="..."
)显示其用法,但没有解释仅将其用作v-on="..."
。
有人可以在Vuetify示例中解释此语法及其用法吗?
答案 0 :(得分:5)
<!-- object syntax (2.4.0+) --> <button v-on="{ mousedown: doThis, mouseup: doThat }"></button>]
所以基本上@click="..."
等于v-on:click="..."
等于v-on="{click:...}"
genActivator () { const node = getSlot(this, 'activator', Object.assign(this.getValueProxy(), { on: this.genActivatorListeners(), attrs: this.genActivatorAttributes(), })) || [] this.activatorNode = node return node }
如果要抽象化组件并一次向下传递多个侦听器,而不是编写多行分配,则很有用。
考虑一个组件:
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>
鉴于上面的组件,您可以访问广告位属性并将其传递到您的自定义组件中:
<ExampleComponent>
<template v-slot:activator="{ on, otherSlotPropName }">
<v-btn
color="red lighten-2"
dark
v-on="on"
>
Click Me
</v-btn>
</template>
<ExampleComponent />
从上方比较组件-用render function代替模板:
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
}
]
}
}
在v-on="eventsObject"
为空的情况下,将调用方法bindObjectListener
,从而将事件分配给data.on
。
这发生在createComponent
scope中。
最后,listeners
作为VNodeComponentOptions
传递并由updateListeners
更新。
考虑到可以加入和扩展vue实例时,人们可以说服自己将任何组件简化为更原子的版本。
这是Vuetify在例如通过创建activator mixin
来创建v-dialog
组件。
现在,您可以跟踪activatable
挂载的on
的内容:
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 },
}
}
在上面的代码段中,剩下的就是将其实现到实际组件中了:
// 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)
}
})