Как создать разбиение на страницы как дочерний компонент, который можно повторно использовать в VueJS

В настоящее время я использую Element-UI для быстрой разработки в своих приложениях, и я хочу создать разбиение на страницы в качестве дочернего компонента, чтобы я мог повторно использовать его в любом родительском компоненте и уменьшить размер своего приложения.

Пример для моего родительского компонента, у которого есть «встроенная» разбивка на страницы.

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>

Это работает очень хорошо, но это может быть болезненно, потому что я должен повторить все это в любом компоненте, который хочет использовать разбиение на страницы. Любой может дать мне пример того, как создать эту разбивку на страницы как дочерний компонент, в то время как коллекции все еще остаются в родительском компоненте.

Я уже пытался его создать, но застрял в том, как передать возвращаемое значение из вычисляемого свойства родительскому компоненту.

Пример, моя неудавшаяся пробная версия создает дочерний компонент

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
    }   
}

person Muhammad Izzuddin Al Fikri    schedule 13.03.2018    source источник


Ответы (1)


ОБНОВЛЕНО

Немного повозившись, наконец-то я могу это решить.

Вычисляемый массив должен храниться в родительском компоненте и добавлять объект, в котором хранятся begin и end индексы для нарезки в массиве коллекции. Какой этот объект будет изменен на основе дочерних событий с использованием методов.

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
    }
}

А затем в дочернем компоненте вычисленная логика переместилась на метод, который обрабатывает событие от щелкнувшего элемента разбиения на страницы.

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)
    }
}
person Muhammad Izzuddin Al Fikri    schedule 13.03.2018