在vue v-menu组件中重新定义激活器插槽

时间:2020-01-15 11:13:24

标签: javascript vue.js vuetify.js

我正在尝试基于vuetify的 v-menu 组件创建自定义组件。

应该从vuetify的对话框中两次调用此菜单:

  1. 通过点击对话框内容顶部的“添加行”按钮
  2. 通过按 v-data-table 组件的每一行上的“编辑”图标按钮

在两种情况下均应显示相同的菜单。主要区别在于用于调用菜单的组件-在第一种情况下,它应该是 v-btn 并带有一些文本,在第二种情况下,它应该是 v-icon 图标。

根据vue和vuetify文档,我认为我应该重新定义 v-slot:activator ,但是我遇到了一些问题:该组件始终具有v-slot:activator的默认值

Vue 2.6.11,Vuetify 2.2.3

我的代码如下所示:

Dialog.vue:

<template>
  <v-dialog v-model="dialog" max-width="500px" persistent>
    <v-card>
      <v-card-title>
        <v-spacer></v-spacer>
        <menu-component/>
      </v-card-title>
      <v-card-text>
        <v-data-table
          :headers="tableHeaders"
          :items="tableContent"
        >
          <template v-slot:item="props">
            <tr>
              <td>{{ props.item.id }}</td>
              <td>{{ props.item.text }}</td>
              <td class="text-center">
                <menu-component>
                  <template v-slot:activator="{ on }">
                    <v-icon v-on="on">mdi-pencil</v-icon>
                  </template>
                </menu-component>
              </td>
            </tr>
          </template>
        </v-data-table>
      </v-card-text>
      <v-card-actions>
        <v-spacer></v-spacer>
        <v-btn @click="close">{{ "Close dialog" }}</v-btn>
      </v-card-actions>
    </v-card>
  </v-dialog>
</template>

<script>
  import MenuComponent from "./MenuComponent";

  export default {
    components: {
      'menu-component': MenuComponent
    },
    data() {
      return {
        tableContent: [
          { id: 1, text: 'some text'}
        ],
        tableHeaders: [
          {text: 'ID'},
          {text: 'Text'},
          {text: 'Actions', align: 'center'}
        ]
      }
    },
    props: {
      dialog: Boolean
    },
    methods: {
      close() {
        this.$emit('close-dialog');
      }
    }
  }
</script>

MenuComponent.vue:

<template>
  <v-menu bottom left
          v-model="menu"
          :close-on-content-click="false">
    <template v-slot:activator="{ on }">
      <v-btn v-on="on">Add row</v-btn>
    </template>
    <v-card width="300">
      <v-container>
        <v-layout wrap>
          <v-text-field label="Text"/>
        </v-layout>
      </v-container>
      <v-card-actions>
        <v-spacer></v-spacer>
        <v-btn @click="menu=false">{{ "Close" }}</v-btn>
      </v-card-actions>
    </v-card>
  </v-menu>
</template>

<script>
  export default {
    data() {
      return {
        menu: false,
      }
    }
  }
</script>

我要做什么:

expected

现在发生的事情:

current

1 个答案:

答案 0 :(得分:3)

是的!您要做的就是将插槽传递给儿童包裹的组件。一个人在这里示意了要点:https://gist.github.com/loilo/73c55ed04917ecf5d682ec70a2a1b8e2#gistcomment-3121626

这是您应该写到MenuComponent.vue中的内容:

<template>
  <v-menu bottom left
    v-model="menu"
    :close-on-content-click="false"
  >

    <!-- pass through scoped slots -->
    <template v-for="(_, scopedSlotName) in $scopedSlots" v-slot:[scopedSlotName]="slotData">
      <slot :name="scopedSlotName" v-bind="slotData" />
    </template>

    <!-- pass through normal slots -->
    <template v-for="(_, slotName) in $slots" v-slot:[slotName]>
      <slot :name="slotName" />
    </template>


    <v-card width="300">
      <v-container>
        <v-layout wrap>
          <v-text-field label="Text"/>
        </v-layout>
      </v-container>
      <v-card-actions>
        <v-spacer></v-spacer>
        <v-btn @click="menu=false">{{ "Close" }}</v-btn>
      </v-card-actions>
    </v-card>
  </v-menu>
</template>

为此,每个插槽将通过您的父组件传递到您的子组件。

这将适用于组件的每个插槽。但是,您可以编写适用于您的用例的代码,如下所示:

<template>
  <v-menu bottom left
    v-model="menu"
    :close-on-content-click="false"
  >

    <!-- pass through scoped slots -->
    <template v-slot:activator="slotData">
      <slot v-if="$scopedSlots.activator" name="activator" v-bind="slotData" />
      <v-btn v-else v-on="slotData.on">Add row</v-btn>
    </template>


    <v-card width="300">
      <v-container>
        <v-layout wrap>
          <v-text-field label="Text"/>
        </v-layout>
      </v-container>
      <v-card-actions>
        <v-spacer></v-spacer>
        <v-btn @click="menu=false">{{ "Close" }}</v-btn>
      </v-card-actions>
    </v-card>
  </v-menu>
</template>