簡體   English   中英

Vue 2 向父組件添加插槽

[英]Vue 2 add slot to parent component

我遇到了Vue 2的問題。 我有一個名為search.vue <product-search></product-search>的主要組件。 這個組件有一個屬性叫做:view ,這個視圖可以是表格、小列、中列等等。 所有這些視圖都是自定義組件: table_view.vuesmall_columns.vue等。在我的視圖中,我有一個名為 actions <slot name="actions"></slot> 現在我想從主組件 (product-search.vue) 添加操作並將它們傳遞給視圖組件。 例如:

有誰知道我如何實現這一目標?

為了更好地閱讀,我減少了代碼量。

空白頁.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>

搜索.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>

您有兩種解決方案:通過子組件將其作為道具從父組件傳遞給孫組件。

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

然后使用 v-html 來渲染它,以防它有一些 html 標簽

或將其作為道具傳遞給孩子並使用那里的插槽將其傳遞給孫子。

第一個解決方案

空白頁.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>

搜索.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 示例中所做的那樣,將 props 傳遞給插槽

table_view.vue :保持不變

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM