在Web应用开发中,前端常常要展示数据列表,数据较多时就要对查询结果进行分页,只显示当前页的数据,一方面不会造成数据列表过长,另一方面减少每次查询和返回的数据量。Laravel 中实现数据分页非常简单,使用 Element-UI 完成分页数据的前端展示同样非常简单。
一、Laravel 分页
1、在其他框架中,分页操作可能比较复杂。Laravel 不管使用数据库查询构造器 或者 Eloquent ORM ,都可以非常方便、易用的完成数据库查询结果集分页操作。数据分页至少需要两个参数:一是每页多少条数据,二是当前显示第几页。Laravel 数据分页有多种方法,最简单的是使用 paginate 方法。默认情况下,HTTP 请求中的 page 查询参数值被当作当前页的页码。Laravel 会自动检测该值,并自动将其插入到分页器生成的链接中。
2、以查询 User 模型数据为例,先创建路由。
Route::middleware('auth:api')->prefix('v1')->group(function() {
Route::apiResource('users', 'UserController');
}
这样定义之后在以 get 方法请求 api/v1/users 路径时,默认情况下是控制器 UserController 的 index 方法。
3、在 UserController.php 文件中定义 index 方法:
public function index(Request $request)
{
//分页, 参数size是每页查询多少条数据,另一个参数 page 会自动检测
$pageSize = $request->query('size');
$result = User::paginate($pageSize);
return $this->success($result);
}
page 是默认参数,会自动检测,所以这里只出现了一个自定义参数 size,表示每页查询的数据条数。在 Laravel 中 get 请求参数可以用 query 方法接收。success 是自定义的一个方法,用于定义并转化要返回的 json 格式数据。
4、返回结果示例。
其中 size 为 3,page 为 2。返回数据除了 data ,还有两个重要参数:一是当前页 current_page,也就是 URL 参数中的 page,另一个是 total,表示 User 表中所有数据的总数。有了 total 、size、current_page 三个参数,就可以推断出其它参数,所以返回数据中给出的上一页、下一页、最后一页的值及 URL 在后续的程序中并不会使用。
请求地址:http://zhangschool.test/api/v1/users?size=3&page=2
{
"status": "success",
"code": 200,
"data": {
"current_page": 2,
"data": [
{
"id": 5,
"name": "bbb",
"email": "bbb@qq.com",
"email_verified_at": null,
"created_at": "2019-03-24 15:39:52",
"updated_at": "2019-03-24 15:39:52",
"avatar": null,
"introduction": null
},
{
"id": 6,
"name": "dfee",
"email": "433dd@qq.com",
"email_verified_at": null,
"created_at": "2019-03-25 22:10:17",
"updated_at": "2019-04-09 21:14:52",
"avatar": null,
"introduction": null
},
{
"id": 7,
"name": "中&国",
"email": "4d@qq.com",
"email_verified_at": null,
"created_at": "2019-03-25 22:10:33",
"updated_at": "2019-03-25 22:10:33",
"avatar": null,
"introduction": null
}
],
"first_page_url": "http://zhangschool.test/api/v1/users?page=1",
"from": 4,
"last_page": 4,
"last_page_url": "http://zhangschool.test/api/v1/users?page=4",
"next_page_url": "http://zhangschool.test/api/v1/users?page=3",
"path": "http://zhangschool.test/api/v1/users",
"per_page": "3",
"prev_page_url": "http://zhangschool.test/api/v1/users?page=1",
"to": 6,
"total": 12
}
}
二、vue-element-admin 前端框架
1、Element-UI 是基于 Vue 2.0 的桌面端组件库,内置有 Pagination 分页组件。vue-element-admin 是一个后台前端解决方案,它基于 vue 和 element-ui 实现,vue-admin-template 是其简化版。本示例使用 vue-admin-template ,完成基础框架的构建。
2、在 router/index.js 文件中先添加路径。
{
path: 'user',
name: 'User',
component: () => import('@/views/user/index'),
meta: { title: '用户管理', icon: 'table' }
},
3、在 views/user 目录下创建文件 index.vue,用 el-table 组件显示数据。示例代码:
<template>
<el-card class="box-card">
<el-table
v-loading="loading"
:data="tableData"
style="width: 100%"
>
<el-table-column
prop="id"
label="ID"
width="180"
/>
<el-table-column
prop="name"
label="用户名"
width="180"
/>
<el-table-column
prop="email"
label="邮箱"
width="180"
/>
<el-table-column
prop="status"
label="状态"
width="90"
/>
<el-table-column label="操作" width="230px">
<template slot-scope="scope">
<el-dropdown split-button type="primary" @click="handleView(scope.row)">
查看
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>
<el-button
type="text"
@click="handleChangeStatus(scope.row)"
>切换状态</el-button>
</el-dropdown-item>
<el-dropdown-item>
<el-button
type="text"
@click="handleEdit(scope.row)"
>编辑</el-button>
</el-dropdown-item>
<el-dropdown-item><el-button
type="text"
@click="handleDelete(scope.row)"
>删除</el-button>
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-table-column>
</el-table>
4、接着,采用 el-pagination 分页组件,继续编辑 index.vue 文件,其中属性 page-size 是每页请求多少条数据,total 是指一共有多少数据。另外还有四个事件分别绑定了四个函数,分别在切换当前页、改变请求条数(即 page-size 值)、点击上一页、点击下一页时触发。
<el-pagination
background
layout="total, sizes, prev, pager, next, jumper"
:page-sizes="[2, 5, 10, 20]"
:page-size="pageSize"
:current-page="currentPage"
:total="total"
@current-change="handleCurrentChange"
@prev-click="handlePrevClick"
@next-click="handleNextClick"
@size-change="handleSizeChange"
/>
</el-card>
</template>
5、在 api 目录下,新建 user.js 文件并编辑,示例代码:
import request from '@/utils/request'
export function userIndex(pageSize, currentPage) {
return request({
url: '/users?size=' + pageSize + '&page=' + currentPage,
method: 'get'
})
}
其中 request 是 vue-admin-template 框架中向后端发起请求的文件,封装的发起请求的 http 客户端是 axios 。最终请求的 url 示例:
http://zhangschool.test/api/v1/users?size=3&page=2
6、user/index.vue 文件中 script 部分代码如下:
<script>
import { userIndex } from '@/api/user'
export default {
data() {
return {
loading: false,
tableData: [],
total: 0,
currentPage: 1, // 当前页码
pageSize: 2 // 默认分页条数
}
},
mounted() {
this.getUserIndex()
},
methods: {
// 用户信息列表 pageSize 分页条数,currentPage 是当前页数
getUserIndex() {
return new Promise((resolve, reject) => {
this.loading = true
userIndex(this.pageSize, this.currentPage)
.then(response => {
console.log('users index.vue', response.data)
this.total = response.data.total
this.tableData = response.data.data
this.currentPage = response.data.current_page
this.loading = false
resolve()
})
.catch(error => {
this.loading = false
reject(error)
})
})
},
handleCurrentChange($var) {
console.log('当前页: ', $var)
this.currentPage = $var
this.getUserIndex()
},
handlePrevClick($var) {
console.log('上一页: ', $var)
this.currentPage = $var
this.getUserIndex()
},
handleNextClick($var) {
console.log('下一页: ', $var)
this.currentPage = $var
this.getUserIndex()
},
handleSizeChange($var) {
console.log('size change: ', $var)
this.pageSize = $var
this.currentPage = 1
this.getUserIndex()
}
}
}
</script>
引入request.js 中定义的方法 userIndex()
data 数据的5个属性, loading 表示数据加载中、tableData 是表格数据, total 是所有数据总条数,total 要给定个默认值,不能为空。currentPage 是当前页码,默认值就是第1页,即在 URL 中 page=1。pageSize 是每页获取多少条数据,默认值和 el-pagination 组件 page-sizes 数组第一个元素的值相同。
在 mounted 中调用 getUserIndex() 函数,即在 vue 完成页面模版渲染后即向后台请求数据。
定义 getUserIndex() 函数,向后端发起请求,请求成功之后,按前述返回结果中的 json 数据结构,给 data 中定义的属性赋值,表格中数据就正常显示了。
切换当前页等四个事件所绑定的函数都会接收一个参数 $var,这个参数就是当前事件的值。 这就好办了,用这个新的 $var 的值改变 data 中相应的属性值,再调用 getUserIndex() 函数重新向后台请求数据。
三、最终完成结果
本案例采用 Laravel 6.X ,vue-admin-template 4.1.0,element-ui 2.7.2,很容易就完成了后端数据分页和前端的数据列表分页展示。
---END---
敬请关注『飞飞编程』,为技术披上艺术的嫁衣,融在教育的生命中!