如何在 VueJS 中包装组件? [英] How to wrap a component in VueJS?

查看:23
本文介绍了如何在 VueJS 中包装组件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Of course, UI components are already wrapped enough conveniently. But, I want to reuse some components with custom options.

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

如果所有视图具有完全相同的标题和数据,则没有问题.当每个视图有不同的数据时,它不起作用.

If all views have completely same header and data, it's no problem. When each views have different data, it's not working.

这是我的代码:

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

I want to write only tbody in Main.vue (and other views), and other optional elements in the Wrapper.vue.

推荐答案

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

In order to wrap a component you should use the following syntax.

  • inheritAttrs: falsev-bind:$attrs:在组件上使用该选项将包装器中使用的所有属性传递给目标组件.
  • v-for=(index, name) in $scopedSlots";v-slot:[name]=data":使用它来迭代目标组件上定义的所有槽,并在包装​​器中定义它们.
  • v-on:$listeners:使用该选项通过包装器传递来自目标组件的所有事件.
  • inheritAttrs: false and v-bind:$attrs: Use that option on the component to pass all attributes used in the wrapper to the target component.
  • v-for="(index, name) in $scopedSlots" v-slot:[name]="data" and <slot :name="name" v-bind="data"></slot>: Use that to iterate over all slots defined on the target component, and define them in the wrapper either.
  • v-on:$listeners: Use that option to pass all events coming from the target component throug the wrapper.

在定义所有这些之后,包装器将按需要工作.它只会包装组件.然后您可以添加您的自定义设置.

After defining all that, the wrapper will work as desired. It'll just wrap the component. Then you can add your customizations.

包装

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

这篇关于如何在 VueJS 中包装组件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆