v-on="..." 语法在 VueJS 中意味着什么?

问题描述 投票:0回答:1

我遇到了 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
指令指定事件时,这意味着什么?

v-on

上的VueJS文档仅显示其与明确指定的事件名称(例如
v-on:click="..."
)结合使用的用法,但没有解释仅将其用作
v-on="..."

有人可以解释一下这个语法及其在 Vuetify 示例中的用法吗?

javascript vue.js vuetify.js
1个回答
50
投票

TLDR:

基本用法

<!-- object syntax (2.4.0+) --> 
<button v-on="{ mousedown: doThis, mouseup: doThat }"></button>]

所以基本上

@click="..."
等于
v-on:click="..."
等于
v-on="{click:...}"


TLDR:

vuetify 实现:

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 />

有时用纯 JavaScript 更容易看到它:

比较上面的组件 - 使用 渲染函数 而不是模板:

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 实现:

当考虑到可以加入和扩展 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)
  }
})

© www.soinside.com 2019 - 2024. All rights reserved.