优秀的编程知识分享平台

网站首页 > 技术文章 正文

Laravel + Element 超简单实现分页效果案例教程

nanyue 2024-08-03 17:47:49 技术文章 7 ℃

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


敬请关注『飞飞编程』,为技术披上艺术的嫁衣,融在教育的生命中!

最近发表
标签列表