vue.js - 如何在 VueJS 中包装一个组件?

标签 vue.js

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

特别是,我想重用data tables component .

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

这是我的代码:

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(和其他 View )中编写 tbody,并在 Wrapper.vue 中编写其他可选元素。

最佳答案

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

  • inheritAttrs: falsev-bind:$attrs : 在组件上使用该选项将包装器中使用的所有属性传递给目标组件。
  • v-for="(index, name) in $scopedSlots" v-slot:[name]="data"<slot :name="name" v-bind="data"></slot> : 使用它来遍历目标组件上定义的所有插槽,并在包装​​器中定义它们。
  • 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>

关于vue.js - 如何在 VueJS 中包装一个组件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49011329/

相关文章:

javascript - 将 vuex 的状态传递给图表 - vue

vue.js - Vuejs : how to mix static and dynamic content in template?

javascript - Nuxt.js-共享持久数据的链接: how the receiver can view the data?

vue.js - 如何在 Vue SFC 中使用条件模板标签

javascript - 如何在 vue 3 中删除已弃用的 $listeners

javascript - Vue Js 中 @import sass 文件的问题

vue.js - 如何在 vue.js 版本 3 中上传文件

javascript - v-show 未按预期工作

javascript - 如何在 'value' 输入之前修改 VueJS 中的 `$emit(' prop')`完成更新

javascript - Vue meta 没有得到更新