V-образный слот для доступа Vuetify:элемент в пользовательском компоненте, доступном для данных

#vue.js #vue-component #vuetify.js

Вопрос:

Здравствуйте, я сделал пользовательский компонент для обработки данных, мой файл Table.vue выглядит так:

 <template>
    <div>
        <v-data-table
            :headers="headers"
            :items="items"
            :search="search"
            :loading="loading"
            loading-text="Loading... Please wait"
            dense
            >
            <template v-slot:top>
                <v-toolbar dark flat dense>
                    <v-toolbar-title>{{ title }}</v-toolbar-title>
                    <v-spacer></v-spacer>
                    <v-text-field
                        v-model="search"
                        append-icon="mdi-magnify"
                        label="Search"
                        single-line
                        hide-details
                        ></v-text-field>
                    <v-spacer></v-spacer>
                </v-toolbar>
            </template>
        </v-data-table>
    </div>
</template>

<script>
    export default {
        name: "Table",
        props: [
            "headers",
            "items",
            "title",
            "itemsPerPage",
            "loading",
        ],
        data: function () {
            return {
                search: '',
            }
        },
        methods: {
        },
    };
</script>
 

И я использую его именно так:

 <Table
    :headers="headers"
    :items="groups"
    :loading="loading"
    title="Baseny"
    >
</Table>
 

Все в порядке, но я хочу добавить пользовательские столбцы с действиями для каждого ввода (каждый ввод имеет другой идентификатор).

Обычно без специального компонента я пишу так:

 <v-data-table
            :headers="headers"
            :items="times"
            :items-per-page="5"
            :search="search"
            :loading="loading"
            loading-text="Ładowanie... Proszę czekać"
            >

            <template v-slot:top>
                <v-toolbar dark flat dense>
                    <v-toolbar-title>Lista zajęć</v-toolbar-title>
                    <v-spacer></v-spacer>
                    <v-text-field
                        v-model="search"
                        append-icon="mdi-magnify"
                        label="Szukaj"
                        single-line
                        hide-details
                        ></v-text-field>
                    <v-spacer></v-spacer>
                    <v-btn
                        color="primary"
                        :to="{ name: 'admin.times.create' }"
                        >
                        Dodaj zajęcie
                    </v-btn>
                </v-toolbar>
            </template>

            <template v-slot:item.actions="{ item }">
                <v-icon
                    small
                    class="mr-2"
                    @click="show(item)"
                    >
                    mdi-pool
                </v-icon>
                <v-icon
                    small
                    class="mr-2"
                    @click="edit(item)"
                    >
                    mdi-pencil
                </v-icon>
            </template>
        </v-data-table>
 

Я использую этот v-образный слот:

 <template v-slot:item.actions="{ item }">
                <v-icon
                    small
                    class="mr-2"
                    @click="show(item)"
                    >
                    mdi-pool
                </v-icon>
                <v-icon
                    small
                    class="mr-2"
                    @click="edit(item)"
                    >
                    mdi-pencil
                </v-icon>
            </template>
 

Но когда я писал пользовательский компонент таблицы многократного использования, он не работал, когда я вставлял эти строки в тег. Как это сделать?

Ответ №1:

То, чего вы хотите достичь, я считаю компонентом-оболочкой. Вы хотите обернуть компонент поверх другого, чтобы у него были некоторые пользовательские свойства, которые вы хотите повторно использовать в своем приложении.

Что вам нужно, так это небольшой фрагмент, который позволит использовать ваши слоты:

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

Вы можете найти источник этого здесь

В принципе, вот как вы можете переписать свой пользовательский файл.vue:

 <template>
  <div>
    <v-data-table
      v-bind="$attrs"
      v-on="$listeners"
      :search="search"
      loading-text="Loading... Please wait"
      dense
    >
      <!-- 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>
      <template v-slot:top>
        <v-toolbar dark flat dense>
          <v-toolbar-title>{{ title }}</v-toolbar-title>
          <v-spacer></v-spacer>
          <v-text-field
            v-model="search"
            append-icon="mdi-magnify"
            label="Search"
            single-line
            hide-details
          ></v-text-field>
          <v-spacer></v-spacer>
        </v-toolbar>
      </template>
    </v-data-table>
  </div>
</template>

<script>
export default {
  name: "CustomTable",
  props: ["title"],
  data: function () {
    return {
      search: "",
    };
  },
  methods: {},
};
</script>
 

Я сделал codesandbox, чтобы показать вам, как это работает:
https://codesandbox.io/s/vuetify-2-forked-3lp9y?file=/src/components/CustomTable.vue

Я также добавил автоматические привязки атрибутов и прослушивателей в вашу таблицу, чтобы вы могли использовать все функции, предоставляемые Vuetify.