Vue 3 - Emit event from child component within a slot

爱⌒轻易说出口 提交于 2021-01-24 11:35:07

问题


I'm looking at upgrading to v3 and was disappointed to see inline-template has been removed. Therefore I'm trying to convert to use a scoped slot instead.

I have defined the following list component:

<template>
    <slot :items="filteredItems" :page="page" :totalPages="totalPages" :onPageChanged="onPageChanged"></slot>
</template>

<script>
    export default {
        props: {
            items: {
                type: Array
            },
            initialPage: {
                type: Number,
                default: 1,
            },
            pageSize: {
                type: Number,
                default: 10
            }
        },
        beforeCreate() {
            this.page = this.initialPage;
        },
        computed: {
            filteredItems() {
                return this.items.slice((this.page - 1) * this.pageSize, this.page * this.pageSize);
            },
            totalPages() {
                return Math.ceil(this.items.length / this.pageSize);
            }
        },
        methods: {
            onPageChanged(page) {
                console.log('Page changed!!!');

                this.page = page;
            }
        }
    };
</script>

Which is called like so:

<list :items="[ { foo: 'A' }, { foo: 'B' }, { foo: 'C' } ]" :page-size="2" #="{ items, page, totalPages, onPageChanged }">
    <ul class="list-group">
        <li class="list-group-item" v-for="item in items">{{ item.foo }}</li>
    </ul>
    <pager :page="page" :total-pages="totalPages" @pageChanged="onPageChanged"></pager>
</list>

Here's the pager component:

<template>
    <ul class="pagination">
        <li class="page-item" v-if="hasPreviousPage"><a href="#" @click="changePage(1)" class="page-link">&laquo;</a></li>
        <li class="page-item" v-if="hasPreviousPage"><a href="#" @click="changePage(page - 1)" class="page-link">&#8249;</a></li>
        <li v-for="page in pages" :class="['page-item', { active: page.isActive }]"><a href="#" @click="changePage(page.name)" class="page-link">{{ page.name }}</a></li>
        <li class="page-item disabled" v-if="page < totalPages - 2"><span class="page-link"> ... </span></li>
        <li class="page-item" v-if="page < totalPages - 2"><a href="#" @click="changePage(totalPages)" class="page-link">{{ totalPages }}</a></li>
        <li class="page-item" v-if="hasNextPage"><a href="#" @click="changePage(page + 1)" class="page-link">&#8250;</a></li>
        <li class="page-item" v-if="hasNextPage"><a href="#" @click="changePage(totalPages)" class="page-link">&raquo;</a></li>
    </ul>
</template>

<script>
    export default {
        props: {
            page: {
                type: Number,
                required: true
            },
            totalPages: {
                type: Number,
                required: true
            }
        },
        computed: {
            hasPreviousPage() {
                return this.page > 1;
            },
            hasNextPage() {
                return this.page < this.totalPages;
            },
            pages() {
                const range = [];

                for (let i = this.page <= 2 ? 1 : this.page - 2; i <= (this.page >= this.totalPages - 2 ? this.totalPages : this.page + 2); i++) {
                    range.push({
                        name: i,
                        isActive: this.page == i
                    });
                }

                return range;
            }
        },
        methods: {
            changePage(page, e = event) {
                e.preventDefault();

                // Trigger the page changed event.
                this.$emit('pageChanged', page);
            }
        }
    };
</script>

However whenever I try to change the page, the changePage method is invoked which emits the pageChanged event, but it doesn't invoke the onPageChanged method within the list component.

I'd appreciate if someone could show me what I'm doing wrong. Thanks


回答1:


The event name should be written in kebab-case format as follows :

this.$emit('page-changed', page);

and use it like @page-changed="onPageChanged



来源:https://stackoverflow.com/questions/64106118/vue-3-emit-event-from-child-component-within-a-slot

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!