简体   繁体   中英

How to create pagination as child component that reusable in VueJS

Currently i am using Element-UI for rapid development in my apps and i want to create pagination as child component, so i can reusable it in any parent component and reduce the size of my app.

Example for my parent component that has 'inline' pagination.

parent.vue

<template>
    <ol>
        <li v-for="student in studentList>{{ student.full_name }}</li>
    </ol>
    <el-pagination
        layout="sizes, prev, pager, next"
        :total="totalPages"
        :page-size="pageSize"
        :page-sizes="[10, 25, 50, 100]"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange">
    </el-pagination>
</template>
<script>
    export default {
        data () {
            return {
                pageSize: 10,
                currentPage: 1,
                students: [] // this filled from backend when component created
            }
        },
        created () {
            // Axios HTTP request to fetch data from server
            // to filled students variable
        },
        computed: {
            totalPages () {
                return this.students.length
            },
            studentList () {
                return this.students.slice(((this.currentPage - 1) * this.pageSize), (this.pageSize * this.currentPage))
            }
        },
        methods: {
            handleSizeChange (size) {
                this.pageSize = size
            },
            handleCurrentChange (value) {
                this.currentPage = value
            }
        }
    }
</script>

It works very well, but it can be pain because I should repeat all of that stuff in any component that want to use pagination. Anyone can give me example how to create this pagination as child component while the collections still remain on parent component.

I've already try to create it, but stuck to how pass returned value from computed property to parent component.

Example, my failed trial create child component

child.vue

... // all of template element and functions
computed: {
    studentList () {}
},
methods: {
    updateStudentList () {
        this.$emit('changed-value', this.studentList) // as you can see, studentList is computed function like parent code above
    }
}

parent.vue

// there's no more studentList function on computed property in parent component
// instead, it moved on child component
<li v-for="student in students">{{ student.full_name }}</li>
<child-pagination v-on:changed-value="rebuildStudent"></child-pagination>
...
methods: {
    rebuildStudent (newCollection) {
       this.students = newCollection
    }   
}

UPDATED

After tinkering a bit, finally i can solve it.

Computed array should be keep on parent component, and add an object that store begin and end index for sliced on collection array. Which that object will changed based on child events using methods.

parent.vue

<template>
    <pagination v-model="pageIndex"
        v-on:paginationInit="paginationInit"
        collections="students">
    </pagination>
</template>

data () {
    return {
        students: [] // collection
        pageIndex: {}
    }
},
computed: {
    studentList () {
        return this.students.slice(pageIndex.begin, pageIndex.end)
    }
},
methods: {
    // This method emitted from child component
    paginationInit (pageIndex) {
        this.pageIndex.begin = pageIndex.begin
        this.pageIndex.end = pageIndex.end
    }
}

And then in child component, the computed logic moved on a method here that handle event from clicked pagination element.

child.vue

data () {
    return {
        pageIndex: { begin: 0, end: 10 }
    }
},
created () {
    this.init()
},
methods: {
    init () {
        this.$emit('paginationInit', this.pageIndex)
    },
    handleCurrentChange (page) {
        this.pageIndex.begin = (page - 1) * this.pageSize
        this.pageIndex.end = this.pageSize * page
        this.$emit('input', this.pageIndex)
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM