【问题标题】:How to wrap a component in VueJS?如何在 VueJS 中包装组件?
【发布时间】:2018-02-27 14:43:50
【问题描述】:

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

特别想重用data tables component

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

这是我的代码:

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 中编写其他可选元素。

【问题讨论】:

  • 请定义“它不工作”。不清楚是什么问题。

标签: vue.js


【解决方案1】:

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

  • inheritAttrs: falsev-bind:$attrs:在组件上使用该选项将包装器中使用的所有属性传递给目标组件。
  • v-for="(index, name) in $scopedSlots" v-slot:[name]="data"&lt;slot :name="name" v-bind="data"&gt;&lt;/slot&gt;:使用它来遍历目标组件上定义的所有槽,并在包装​​器中定义它们。
  • v-on:$listeners:使用该选项将来自目标组件的所有事件传递给包装器。

定义完所有内容后,包装器将按需要工作。它只会包装组件。然后您可以添加您的自定义设置。

包装器

<template>
  <v-data-table
    v-bind="$attrs"
    v-on="$listeners"
  >
    <template v-for="(index, name) in $scopedSlots" v-slot:[name]="data">
      <slot :name="name" v-bind="data"></slot>
    </template>
  </v-data-table>
</template>

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'

@Component({
    name: 'BaseTable',
    inheritAttrs: false
})
export default class extends Vue {
}
</script>

【讨论】:

    【解决方案2】:

    它不起作用,因为您的插槽范围的使用不正确。以下更改应该有效。

    包装器.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

    【讨论】:

      猜你喜欢
      • 2018-07-26
      • 2017-11-25
      • 1970-01-01
      • 2018-06-28
      • 2020-10-29
      • 2020-01-16
      • 2021-06-09
      • 1970-01-01
      • 2016-08-03
      相关资源
      最近更新 更多