我如何在列表页面添加分页使用vue js和laravel


How can I add pagination in listing page using vue js and laravel?

我有一个使用vue js和laravel的清单页面。在这个页面中还包括过滤和排序功能。目前,列表、排序和过滤工作正常。我需要在这个清单页面中包含分页。我不知道该怎么说,我的客户需要这个。我在软件方面没有太多的经验。我当前的代码如下所示。你可以检查并帮我整合分页吗?

版本是vue js(1.0.25)和laravel (5.2)

dashboard.blade.php

@extends('layouts.app')
@section('title', 'Dashboard')
@section('style')
    <style>
        th.active .arrow {
            opacity: 1;
        }
        .arrow {
            display: inline-block;
            vertical-align: middle;
            width: 0;
            height: 0;
            margin-left: 5px;
            opacity: 0.66;
        }
        .arrow.asc {
            border-left: 4px solid transparent;
            border-right: 4px solid transparent;
            border-bottom: 4px solid #42b983;
        }
        .arrow.dsc {
            border-left: 4px solid transparent;
            border-right: 4px solid transparent;
            border-top: 4px solid #42b983;
        }
        #search {
            margin-bottom: 10px;
        }
    </style>
@endsection
@section('content')
    <div class="container">
        <div class="row">
            <h1 class="page-header">{{ trans('messages.customerListPageHeadingLabel') }}</h1>
            <template id="grid-template">
                <table class="table table-hover table-bordered">
                    <thead>
                    <tr>
                        <th v-for="key in columns" @click="sortBy(key)" :class="{active: sortKey == key}">@{{ heading[key] }} <span class="arrow" :class="sortOrders[key] > 0 ? 'asc' : 'dsc'"></span>
                        </th>
                    </tr>
                    </thead>
                    <tbody>
                    <tr v-for="(index, customer) in customers | filterBy filterKey | orderBy sortKey sortOrders[sortKey]">
                        <td>@{{ customer.erp_id }}</td>
                        <td>@{{customer.firstname}}</td>
                        <td><a href="{{ url('/customer/details/') }}/@{{ customer.id }}">@{{customer.lastname}}</a></td>
                        <td>@{{customer.email}}</td>
                        <td>@{{customer.phone_1}}</td>
                        <td>@{{customer.status}}</td>
                        <td>@{{customer.created_on}}</td>
                    </tr>
                    </tbody>
                </table>
            </template>
            <div id="app">
                <div class="form-group col-md-4">
                    <form id="search" class="form-inline">
                        <label for="query">{{ trans('messages.customerListPageSearchBox') }} </label>
                        <input name="query" class="form-control" v-model="searchQuery">
                    </form>
                </div>
                <br>
                <customer-grid  :customers="{{$listCustomers}}"  :columns="gridColumns" :heading="colTitles"  :filter-key="searchQuery"></customer-grid>
            </div>
        </div>
    </div>
    @endsection
    @push('script')
            <!-- Vue Js -->
    <script src="/assets/js/vue.js"></script>
    <script src="/assets/js/vue-resource.js"></script>
    <script>
        Vue.component('customer-grid', {
            template: '#grid-template',
            props: {
                customers: Array,
                columns: Array,
                filterKey: String,
                heading:Object
            },
            data: function () {
                var sortOrders = {}
                this.columns.forEach(function (key) {
                    sortOrders[key] = 1
                })
                return {
                    sortKey: '',
                    sortOrders: sortOrders
                }
            },
            methods: {
                sortBy: function (key) {
                    this.sortKey = key
                    this.sortOrders[key] = this.sortOrders[key] * -1
                }
            }
        })
        // bootstrap the demo
        var demo = new Vue({
            el: '#app',
            data: {
                searchQuery: '',
                gridColumns: ['erp_id', 'firstname', 'lastname', 'email', 'phone_1', 'status', 'created_on'],
                gridData: null,
                colTitles: {'erp_id':'@lang('messages.customerListPageTableCustomerNo')', 'firstname':'@lang('messages.customerListPageTableFirstname')', 'lastname':'@lang('messages.customerListPageTableLastname')', 'email':'E-Mail', 'phone_1':'@lang('messages.customerListPageTablePhone')', 'status':'Status', 'created_on':'@lang('messages.customerListPageTableAddedDate')'}
            },
            created: function() {
                this.fetchData()
            },
            methods: {
                fetchData: function () {
                    var self = this;
                    $.get('/', function( data ) {
                        self.gridData = data;
                    });
                }
            }
        });
    </script>
    @endpush

routes.php

Route::get('/', ['as' => 'listCustomersPage', 'uses' => 'CustomerController@index']);

CustomerController.php

public function index()
    {
        $listCustomers    = Customer::select('id', 'erp_id', 'firstname', 'lastname', 'email', 'phone_1', 'status', DB::raw("DATE_FORMAT(created_at, '%d.%m.%Y %H:%i') AS created_on"))
            ->orderBy('id', 'desc')
            ->get();
        return view('dashboard', compact('listCustomers'));
        /*return view('dashboard');*/
    }

如何在Vue中使用Laravel分页的示例:

控制器:

class UserController extends Controller
    {
        public function index()
        {
            return view('user.index', [
                'users' => User::all()->paginate(25),
            ]);
        }
    }

视图:

<div id="app">
    <tr v-for="user in users">
    ... do something here with the user ... 
    <tr>
</div>
Vue:

   new Vue({
            el: '#app',
            data: {
                users: {!! collect($users->items())->toJson() !!}
            },
        });

我已经用Vue .js编写了我自己的分页(我也使用Vue与laravel),因为Vue .js没有开箱使用的分页。我构建了这个组件:

<style>
    li.page-item {
        cursor: pointer;
    }
    li.active_pagination a {
        background-color: #1c84c6 !important;
        border-color: #1c84c6 !important;
        color: #ffffff !important;
    }
</style>
<template>
    <div>
        <ul class="pagination pull-right">
            <li class="page-item" :class="{'disabled': currentPage == 1}">
                <a class="page-link" href="#" @click.prevent="changeCurrentPage(1)" aria-label="Previous">
                    <span aria-hidden="true">&laquo;</span>
                    <span class="sr-only">Previous</span>
                </a>
            </li>
            <li class="page-item" :class="{'disabled': currentPage == 1}">
                <a class="page-link" href="#" @click.prevent="decrementCurrentPage(currentPage)" aria-label="Previous">
                    <span aria-hidden="true">&lsaquo;</span>
                    <span class="sr-only">Previous</span>
                </a>
            </li>
            <li v-for="index in indexes" class="page-item" :class="{'active_pagination': currentPage == index}"><a class="page-link" @click.prevent="changeCurrentPage(index)">{{index}}</a></li>
            <li class="page-item" :class="{'disabled': currentPage == totalPages}">
                <a class="page-link" href="#" @click.prevent="incrementCurrentPage(currentPage)" aria-label="Next">
                    <span aria-hidden="true">&rsaquo;</span>
                    <span class="sr-only">Next</span>
                </a>
            </li>
            <li class="page-item" :class="{'disabled': currentPage == totalPages}">
                <a class="page-link" href="#" @click.prevent="changeCurrentPage(totalPages)" aria-label="Next">
                    <span aria-hidden="true">&raquo;</span>
                    <span class="sr-only">Next</span>
                </a>
            </li>
        </ul>
    </div>
</template>
<script>
    module.exports = {
        props: ['currentPage','totalPages', 'totalShownIndexes'],
        computed:  {
            indexes: function() {
                var temp_pageIndexes = [];
                if (this.totalPages > 1) {
                    if (this.totalPages <= this.totalShownIndexes) {
                        for (var i = 1; i <= this.totalPages; i++) {
                            if (temp_pageIndexes.indexOf(i) == -1) {
                                temp_pageIndexes.push(i);
                            }
                        }
                    }
                    else {
                        var sigma = Math.ceil((this.totalShownIndexes - 1) / 2);
                        if (sigma + this.currentPage >= this.totalPages) {
                            var temp_right = (this.totalPages - this.currentPage);
                            var temp_left = this.currentPage - (sigma + (sigma - temp_right));
                            temp_pageIndexes.push('...');
                            for (var i = temp_left; i <= this.totalPages; i++) {
                                temp_pageIndexes.push(i);
                            }
                        }
                        else if (this.currentPage - sigma <= 1) {
                            var temp_left = sigma - this.currentPage;
                            var temp_right = sigma + (this.currentPage + sigma + temp_left);
                            for (var i = 1; i <= temp_right - 1; i++) {
                                temp_pageIndexes.push(i);
                            }
                            temp_pageIndexes.push('...');
                        }
                        else {
                            for (var i = this.currentPage - sigma; i <= this.currentPage + sigma; i++) {
                                temp_pageIndexes.push(i);
                            }
                            temp_pageIndexes.push('...');
                        }
                    }
                    return temp_pageIndexes;
                }
                else {
                    this.currentPage = 1;
                    this.totalPages = 1;
                    return ['1'];
                }
            }
        },
        methods: {
            changeCurrentPage(newCurrentPage) {
                console.log('newCurrentPage: ' + newCurrentPage);
                if(newCurrentPage > 0 && newCurrentPage < this.totalPages + 1 && newCurrentPage != this.currentPage && newCurrentPage != '...') {
                    this.currentPage = newCurrentPage;
                    this.$parent.pagination.currentPage = this.currentPage;
                }
            },
            incrementCurrentPage(currentPage) {
                this.changeCurrentPage(Number(currentPage) + 1);
            },
            decrementCurrentPage(currentPage) {
                this.changeCurrentPage(Number(currentPage) - 1)
            }
        }
    }
</script>

我建立了这个过滤器:

Vue.filter('paginate', function (list, currentPage, perPage) {
    var totalPages = Math.ceil(list.length / perPage);
    if(totalPages == 0) {
        totalPages = 1;
    }
    this.pagination.totalPages = totalPages;
    var index = (currentPage - 1) * perPage;
    return list.slice(index, index + perPage);
});

您可以将此过滤器放置在过滤/排序列表的末尾,如下所示:

v-for="(index, customer) in customers | filterBy filterKey | orderBy sortKey sortOrders[sortKey] | paginate pagination.currentPage pagination.perPage"

要使其工作,您需要在数据对象中添加分页对象,如下所示:

data() {
    return {
        pagination: {
            options: [200,100,50,25,10,1],
            perPage: 10,
            totalPages: 1,
            currentPage: 1,
            totalShownIndexes: 5
        }
    }
}

options属性是可选的。我用它来填充一个有perPage选择的组合框。因此,您可以选择每页要显示多少项。在选择更改时,您将设置perPage属性

现在你差不多完成了。您只需要这些方法:

changePerPage(perPage) {
    this.pagination.perPage = perPage;
    this.resetCurrentPage();
},
resetCurrentPage() {
    this.pagination.currentPage = 1;
}

changePerPage()方法仅在您想要每个页面选择的组合框时才需要。

resetCurrentPage()方法应该在应用其他过滤器时调用。这就是你所需要做的。

分页可以在雄辩的选择语句中完成,现在您所要做的就是在刀片上设置其外观样式,编辑客户控制器的内容,如下所示

public function index()
{
    $list = Customer::select('id', 'erp_id', 'firstname', 'lastname', 'email', 'phone_1', 'status', DB::raw("DATE_FORMAT(created_at, '%d.%m.%Y %H:%i') AS created_on"))
        ->orderBy('id', 'desc')
        ->get();
    $all = count($list);
    $listCustomers = Customer::select('id', 'erp_id', 'firstname',   'lastname', 'email', 'phone_1', 'status', DB::raw("DATE_FORMAT(created_at, '%d.%m.%Y %H:%i') AS created_on"))
        ->orderBy('id', 'desc')
        ->paginate(10);//note here that im assuming you want to display 10 results per page 
    return view('dashboard', compact('listCustomers', 'all'));
    /*return view('dashboard');*/
}

在仪表板刀片上添加div,指定不同的页面

@section('title', 'Dashboard')
@section('style')
<style>
    th.active .arrow {
        opacity: 1;
    }
    .arrow {
        display: inline-block;
        vertical-align: middle;
        width: 0;
        height: 0;
        margin-left: 5px;
        opacity: 0.66;
    }
    .arrow.asc {
        border-left: 4px solid transparent;
        border-right: 4px solid transparent;
        border-bottom: 4px solid #42b983;
    }
    .arrow.dsc {
        border-left: 4px solid transparent;
        border-right: 4px solid transparent;
        border-top: 4px solid #42b983;
    }
    #search {
        margin-bottom: 10px;
    }
</style>
@endsection
@section('content')
<div class="container">
    <div class="row">
        <h1 class="page-header">{{     trans('messages.customerListPageHeadingLabel') }}</h1>
        <template id="grid-template">
            <table class="table table-hover table-bordered">
                <thead>
                <tr>
                    <th v-for="key in columns" @click="sortBy(key)" :class="{active: sortKey == key}">@{{ heading[key] }} <span class="arrow" :class="sortOrders[key] > 0 ? 'asc' : 'dsc'"></span>
                    </th>
                </tr>
                </thead>
                <tbody>
                <tr v-for="(index, customer) in customers | filterBy filterKey | orderBy sortKey sortOrders[sortKey]">
                    <td>@{{ customer.erp_id }}</td>
                    <td>@{{customer.firstname}}</td>
                    <td><a href="{{ url('/customer/details/') }}/@{{ customer.id }}">@{{customer.lastname}}</a></td>
                    <td>@{{customer.email}}</td>
                    <td>@{{customer.phone_1}}</td>
                    <td>@{{customer.status}}</td>
                    <td>@{{customer.created_on}}</td>
                </tr>
                </tbody>
            </table>
            <div class="w100 categoryFooter"><!--I added this-->
                 <div class="pagination pull-left no-margin-top">
                 {!! $listCustomers->links(null, ['class' => 'pagination no-margin-top']) !!}
            </div>
            <div class="pull-right pull-right col-sm-4 col-xs-12 no-padding text-right text-left-xs">
            <p>Showing 1-10 of {{ $all }} results</p>
            </div>
                        </div>
        </template>
        <div id="app">
            <div class="form-group col-md-4">
                <form id="search" class="form-inline">
                    <label for="query">{{ trans('messages.customerListPageSearchBox') }} </label>
                    <input name="query" class="form-control" v-model="searchQuery">
                </form>
            </div>
            <br>
            <customer-grid  :customers="{{$listCustomers}}"  :columns="gridColumns" :heading="colTitles"  :filter-key="searchQuery"></customer-grid>
        </div>
    </div>
</div>
@endsection
@push('script')
        <!-- Vue Js -->
<script src="/assets/js/vue.js"></script>
<script src="/assets/js/vue-resource.js"></script>
<script>
    Vue.component('customer-grid', {
        template: '#grid-template',
        props: {
            customers: Array,
            columns: Array,
            filterKey: String,
            heading:Object
        },
        data: function () {
            var sortOrders = {}
            this.columns.forEach(function (key) {
                sortOrders[key] = 1
            })
            return {
                sortKey: '',
                sortOrders: sortOrders
            }
        },
        methods: {
            sortBy: function (key) {
                this.sortKey = key
                this.sortOrders[key] = this.sortOrders[key] * -1
            }
        }
    })
    // bootstrap the demo
    var demo = new Vue({
        el: '#app',
        data: {
            searchQuery: '',
            gridColumns: ['erp_id', 'firstname', 'lastname', 'email', 'phone_1', 'status', 'created_on'],
            gridData: null,
            colTitles: {'erp_id':'@lang('messages.customerListPageTableCustomerNo')', 'firstname':'@lang('messages.customerListPageTableFirstname')', 'lastname':'@lang('messages.customerListPageTableLastname')', 'email':'E-Mail', 'phone_1':'@lang('messages.customerListPageTablePhone')', 'status':'Status', 'created_on':'@lang('messages.customerListPageTableAddedDate')'}
        },
        created: function() {
            this.fetchData()
        },
        methods: {
            fetchData: function () {
                var self = this;
                $.get('/', function( data ) {
                    self.gridData = data;
                });
            }
        }
    });
</script>
@endpush

确保将10的值更改为{{$count}}变量,以指定每页显示多少个结果。注意,它很可能是10,这是您的最大值,除了最后一页。祝你好运