我遇到了 v-dialog 组件的 Vuetify 示例,它具有名为 activator 的作用域插槽,定义如下:
<template v-slot:activator="{ on }">
<v-btn
color="red lighten-2"
dark
v-on="on"
>
Click Me
</v-btn>
</template>
我从 VueJS 文档中了解作用域插槽的目的和解构插槽属性的概念,但我不明白
v-on="on"
在此示例中的含义。特别是当未使用 v-on
指令指定事件时,这意味着什么?
上的VueJS文档仅显示其与明确指定的事件名称(例如v-on:click="..."
)结合使用的用法,但没有解释仅将其用作v-on="..."
。
有人可以解释一下这个语法及其在 Vuetify 示例中的用法吗?
<!-- 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 />
比较上面的组件 - 使用 渲染函数 而不是模板:
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
范围。
最后
listeners
作为 VNodeComponentOptions
传递并由 updateListeners
更新。
当考虑到可以加入和扩展 vue 实例时,人们可以说服自己任何组件都可以简化为更原子的版本。
这就是 vuetify 在以下示例中使用的内容:
v-dialog
组件,通过创建 activator mixin
。
现在可以追踪由
on
安装的
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 },
}
}
有了上面的代码片段,剩下的就是将其实现到实际组件中:
// 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)
}
})