如何包装Vuetify的组件?

时间:2018-02-27 14:43:51

标签: vue.js vuetify.js

现在我正在使用Vuetify。

当然,UI组件已经足够方便地包装。 但是,我想重用一些带有自定义选项的组件。

特别是,我想重用数据表组件。

https://vuetifyjs.com/ja/components/data-tables

如果所有视图都有完全相同的标题和数据,那就没问题了。 当每个视图都有不同的数据时,它就无法正常工作。

这是我的代码:

Wrapper.vue

<template>
    <v-card>
        <v-card-title>
            <span class="pr-3">{{ tableTitle }}</span>
            <slot name="actions"/>
            <v-spacer/>
            <v-text-field
                    append-icon="search"
                    label="search"
                    single-line
                    hide-details
                    v-model="search"
            />
        </v-card-title>
        <v-data-table
                :search="search"
                :headers="headers"
                :items="items"
                hide-actions
        >

            <!-- problem is here! -->
            <slot name="items" slot="items" slot-scope="props"></slot>

            <template slot="expand" slot-scope="props">
                <v-card flat>
                    <v-card-text>{{ props.item.note }}</v-card-text>
                </v-card>
            </template>
            <template slot="no-data">
                <v-alert :value="true" color="error" icon="warning">
                    no data.
                </v-alert>
            </template>
            <template slot="no-results">
                <v-alert :value="true" color="error" icon="warning">
                    no result.
                </v-alert>
            </template>
        </v-data-table>
    </v-card>
</template>

<script>
    export default {
        props: {
            tableTitle: {type: String},
            search: {type: String},
            headers: {type: Array},
            items: {type: Array}
        }
    }
</script>

Main.vue

<template>
    <v-layout fluid fill-height justify-center align-center row wrap>
        <v-flex sm12 md12 fill-height>
            <main-custom-table
                    tableTitle="table1"
                    :headers="headers"
                    :items="items"
            >
                <template slot="actions">
                    <v-btn color="info">
                        <v-icon>add</v-icon>
                        add
                    </v-btn>
                </template>

                <!-- problem is here! -->
                <template slot="items">
                    <tr>
                        <td class="text-xs-left">{{ items.id }}</td>
                        <td class="text-xs-left">{{ items.data1 }}</td>
                        <td class="text-xs-left">{{ items.data2 }}</td>
                        <td class="justify-center">
                            <v-btn icon class="mx-0" @click="">
                                <v-icon color="teal">edit</v-icon>
                            </v-btn>
                        </td>
                    </tr>
                </template>

            </main-custom-table>
        </v-flex>    
    </v-layout>
</template>

<script>
    export default {
        name: "main",
        data() {
            return {
                dialog: false,
                search: '',
                headers: [
                    {text: 'ID', value: 'id'},
                    {text: 'DATA1', value: 'data1'},
                    {text: 'DATA2', value: 'data2'}
                ],
                items: [
                    {
                        'id': 1,
                        'data1': 10,
                        'data2': 12,
                        'note': aaaaaa
                    },
                    {
                        'id': 2,
                        'data1': 20,
                        'data2': 13,
                        'note': bbbbbb
                    },
                    {
                        'id': 5,
                        'data1': 30,
                        'data2': 14,
                        'note': cccccc
                    }
                ]
            };
        }
    }
</script>

我想在Main.vue(和其他视图)中只编写tbody,在Wrapper.vue中编写其他可选元素。

感谢您的帮助。

2 个答案:

答案 0 :(得分:1)

为了包装组件,您应该使用以下语法。

  • $andinheritAttrs: false:在组件上使用该选项可将包装器中使用的所有属性传递给目标组件。
  • v-bind:$attrsv-for="(index, name) in $scopedSlots" v-slot:[name]="data":使用它来迭代在目标组件上定义的所有插槽,并在包装​​器中对其进行定义。
  • <slot :name="name" v-bind="data"></slot>:使用该选项可以通过包装传递来自目标组件的所有事件。

定义所有内容后,包装程序将按需工作。它将只包装组件。然后,您可以添加自定义内容。

包装

v-on:$listeners

答案 1 :(得分:0)

它不起作用,因为您使用的插槽范围不合适。下面的更改应该起作用。

Wrapper.vue

<v-data-table
    :search="search"
    :headers="headers"
    :items="items"
    hide-actions
>
    <!-- problem is here! -->
    <slot name="items" v-bind:item="props" slot-scope="props"></slot>

    <template slot="expand" slot-scope="props">
        <v-card flat>
            <v-card-text>{{ props.item.note }}</v-card-text>
        </v-card>
    </template>
    <template slot="no-data">
        <v-alert :value="true" color="error" icon="warning">
            no data.
        </v-alert>
    </template>
    <template slot="no-results">
        <v-alert :value="true" color="error" icon="warning">
            no result.
        </v-alert>
    </template>
</v-data-table>

Main.vue

<template slot="items" slot-scope="item">
    <tr>
        <td class="text-xs-left">{{ item.id }}</td>
        <td class="text-xs-left">{{ item.data1 }}</td>
        <td class="text-xs-left">{{ item.data2 }}</td>
        <td class="justify-center">
            <v-btn icon class="mx-0" @click="">
                <v-icon color="teal">edit</v-icon>
            </v-btn>
        </td>
    </tr>
</template>

有关更多信息,请参见:https://vuejs.org/v2/guide/components-slots.html#Scoped-Slots-with-the-slot-scope-Attribute