Vue 2将插槽添加到父组件

时间:2020-02-06 13:47:17

标签: javascript vue.js vuejs2

我遇到了 Vue 2 的问题。我有一个名为 search.vue <product-search></product-search>的主要组件。该组件具有一个名为:view的属性,该视图可以是表格,小列,中列等。所有这些视图都是自定义组件:table_view.vuesmall_columns.vue等。在我的视图中,我有一个名为动作<slot name="actions"></slot>的插槽。现在,我想将操作从添加到主要组件(product-search.vue)并将它们传递给视图组件。例如:

有人知道我该怎么做到吗?

为了减少阅读量,我减少了代码量。

blank_page.vue

    <template>
        <div>
            <search-product :multiple="false" :shop="shop" v-model="items" display="table" :modal="false">
                    <template slot="table-actions">
                        <div>Here some extra actions</div>
                    </template>
            </search-product>
        </div>
    </template>

    <script>
        export default {
            props: {
                shop: {}
            },
            data() {
                return {
                    items: []
                };
            }
        }
    </script>

search.vue

    <template>
        <div>
            <template>
                <component v-bind:is="getDisplay()" :multiple="multiple" :items="items" v-model="selectedItems"></component>

            </template>
        </div>
    </template>

    <script>
        import SearchButton from './search-button.vue';
        import SearchInput from './input.vue';
        import DisplayTable from './displays/table.vue';
        import DisplaySmallGrid from './displays/small-grid.vue';
        import DisplayMediumGrid from './displays/medium-grid.vue';
        import DisplayLargeGrid from './displays/large-grid.vue';

        export default {
            components: {
                searchButton: SearchButton,
                searchInput: SearchInput,
                displayTable: DisplayTable,
                displaySmallGrid: DisplaySmallGrid,
                displayMediumGrid: DisplayMediumGrid,
                displayLargeGrid: DisplayLargeGrid,
            },
            props: {
                modal: {
                    default: false
                },
                multiple: {
                    default: true
                },
                value: {},
                shop: {},
                display: {
                    default: 'table'
                }
            },
            watch: {
                selectedItems(data) {
                    this.$emit('input', data);
                }
            },
            data() {
                return {
                    q: '',
                    items: [],
                    selectedItems: [],
                    modalOpen: false,
                    templates: {
                        DisplayTable
                    }
                };
            },
            methods: {
                getDisplay() {
                    return 'display' + this.display.charAt(0).toUpperCase() + this.display.slice(1);
                },
                toggleModal() {
                    this.modalOpen = !this.modalOpen;
                }
            }
        }
    </script>

table_view.vue

<template>
    <div :class="panel ? 'card' : ''">
        <div :class="panel ? 'card-body' : ''">
            <table class="table table-striped table-hover">
                <thead>
                <tr>
                    <th>ID</th>
                    <th>Actions</th>
                </tr>
                </thead>
                <tbody>
                <tr v-for="item in items">
                    <td v-text="item.id"></td>

                    <td>
                        <slot name="table-actions"></slot>
                    </td>
                </tr>
                </tbody>
            </table>
        </div>
    </div>
</template>

<script>
    export default {
        props: {
            items: {},
            value: {},
            multiple: {},
            panel: {
                default: true
            }
        },
    }

</script>

1 个答案:

答案 0 :(得分:-1)

您有2个解决方案:通过子组件将其作为道具从父母传递给孙子。

parent:data:yourAction => child:props:yourAction =>孙子:props:yourAction

然后使用v-html呈现它,以防它带有一些html标记

或将其作为道具传递给孩子,并使用那里的插槽将其传递给孙子。

第一个解决方案

blank_page.vue

    <template>
        <div>
            <search-product :multiple="false" :shop="shop" v-model="items" display="table" :modal="false" :yourAction:"yourAction">

            </search-product>
        </div>
    </template>

    <script>
        export default {
            props: {
                shop: {}
            },
            data() {
                return {
                    items: [],
                    yourAction: "Here some stuff"
                };
            }
        }
    </script>

search.vue

    <template>
        <div>
            <template>
                <component v-bind:is="getDisplay()" :multiple="multiple" :items="items" v-model="selectedItems" :yourAction="yourAction"></component>

            </template>
        </div>
    </template>

    <script>
        import SearchButton from './search-button.vue';
        import SearchInput from './input.vue';
        import DisplayTable from './displays/table.vue';
        import DisplaySmallGrid from './displays/small-grid.vue';
        import DisplayMediumGrid from './displays/medium-grid.vue';
        import DisplayLargeGrid from './displays/large-grid.vue';

        export default {
            components: {
                searchButton: SearchButton,
                searchInput: SearchInput,
                displayTable: DisplayTable,
                displaySmallGrid: DisplaySmallGrid,
                displayMediumGrid: DisplayMediumGrid,
                displayLargeGrid: DisplayLargeGrid,
            },
            props: {
                yourAction:{
                default:""
                },
                modal: {
                    default: false
                },
                multiple: {
                    default: true
                },
                value: {},
                shop: {},
                display: {
                    default: 'table'
                }
            },
            watch: {
                selectedItems(data) {
                    this.$emit('input', data);
                }
            },
            data() {
                return {
                    q: '',
                    items: [],
                    selectedItems: [],
                    modalOpen: false,
                    templates: {
                        DisplayTable
                    }
                };
            },
            methods: {
                getDisplay() {
                    return 'display' + this.display.charAt(0).toUpperCase() + this.display.slice(1);
                },
                toggleModal() {
                    this.modalOpen = !this.modalOpen;
                }
            }
        }
    </script>

table_view.vue

<template>
    <div :class="panel ? 'card' : ''">
        <div :class="panel ? 'card-body' : ''">
            <table class="table table-striped table-hover">
                <thead>
                <tr>
                    <th>ID</th>
                    <th>Actions</th>
                </tr>
                </thead>
                <tbody>
                <tr v-for="item in items">
                    <td v-text="item.id"></td>

                    <td v-html="yourAction">
                    </td>
                </tr>
                </tbody>
            </table>
        </div>
    </div>
</template>

<script>
    export default {
        props: {
            yourAction,
            items: {},
            value: {},
            multiple: {},
            panel: {
                default: true
            }
        },
    }

</script>

第二个解决方案

blank_page.vue:与我给您的第一个示例相同,您将自己的行为作为道具来传递

search.vue:您像在blank_page.vue示例中一样,将道具传递到插槽中。

table_view.vue:保持不变