前言
最近在做一個前後端分離的專案,前端使用 Vue
+ Element UI
,而後端則使用 Lumen
做介面開發,其中分頁是必不可少的一部分,本文就介紹如何基於以上環境做一個簡單、可複用的分頁功能。
先說後端
後端做的事情不多,只需要接受幾個引數,根據引數來獲取資料即可。
需要獲取的引數如下:
pageSize
(一頁資料的數量)pageIndex
(第幾頁的資料)
然後就可以根據這兩個引數計算出偏移量,再從資料庫中取出相應的資料。
假如現在給出的引數為:pageSize=10
,pageIndex = 2
,也就是說每一頁要10條記錄,要第二頁。
計算偏移量的公式為:pageSize * (pageIndex - 1)
。
基本程式碼如下:
public function getUser(Request $request){
$pageSize = $request->input('pageSize');
$pageIndex = $request->input('pageIndex');
$offset = $pageSize * ($pageIndex - 1);
return User::offset($offset)
->limit($pageSize)
->get();
}
複製程式碼
後端基本上只需要做這麼多,就可以完成一個分頁的功能了,但還是有幾處地方需要改進一下:
- 給引數一個預設值
- 前端還需要知道整個表的資料的總數
- 把分頁做成一個公用的函式
改進後的程式碼如下:
private $default_page_size = 30;
private $default_page_index = 1;
// 公用分頁
public function pagination($request, $list) {
$pageSize = $request->input('pageSize', $this->default_page_size);
$pageIndex = $request->input('pageIndex', $this->default_page_index);
$offset = $pageSize * ($pageIndex - 1);
$total = $list->count();
$list = $list
->offset($offset)
->limit($pageSize);
return [
'list' => $list->get(),
'total' => $total,
];
}
// 獲取使用者列表
public function getUser(Request $request) {
$list = User::query();
/*
這裡可以做一些查詢之類的操作
*/
return $this->pagination($request, $list);
}
複製程式碼
再說前端
前端相對於需要做的事情就比較多了,需要考慮幾點:
- 獲取資料時需要帶上分頁的引數
- 分頁引數需要進行本地持久化,以免重新整理頁面回到第一頁(後端設定的預設值)
- 同樣要抽象出一個通用的分頁元件
獲取資料
這裡我們用 vuex
來管理狀態,然後在請求時帶上分頁資料:
store.js:
注意:
- 這裡為了方便展示程式碼,並沒有使用模組化,專案中,最好將使用模組化方便管理。
- 這裡預設讀者清楚 ES6 的語法
export default new vuex.Store({
state : {
user : {
list: [],
total: 0,
pageIndex: 1,
pageSize: 10,
}
},
mutations: {
updateUser(state, data) {
state.user = {
...state.user,
...data,
}
},
},
actions: {
async getUser({commit,state,getters}) {
// $axios 只是我自己封裝的一個函式 這裡並不重要
const res = await $axios.get('/user',getters.requestData(state.user))
commit('updateUser',res);
},
},
getters:{
requestData(state) {
return (origin) => {
const {
pageIndex,
pageSize,
} = origin;
const data = {
pageIndex,
pageSize,
};
return data;
}
},
}
})
複製程式碼
資料持久化
現在如何獲取資料已經搞定了,資料持久化我使用 vuex-localstorage,安裝後,只需要在上面程式碼的基礎上新增:
import createPersist from 'vuex-localstorage'
export default new vuex.Store({
// 接著上面的
plugins: [createPersist({
namespace: 'studio-user',
initialState: {},
// ONE_WEEK
expires: 7 * 24 * 60 * 60 * 1e3
})]
})
複製程式碼
公用分頁元件
<template>
<el-Pagination
background
layout="total, sizes, prev, pager, next, jumper"
:total="module.total"
:current-page.sync="module.pageIndex"
:page-sizes="module.pageSizes"
:page-size.sync="module.pageSize"
@current-change="handleCurrentChange"
@size-change="handleSizeChange"
>
</el-Pagination>
</template>
<script>
export default {
props: {
module: Object
},
methods: {
getData() {
this.$emit("get-data");
},
handleCurrentChange() {
this.getData();
},
handleSizeChange(val) {
this.getData();
}
}
};
</script>
複製程式碼
使用分頁元件
<template>
<div class="container">
<el-table
:data="user.list"
style="width: 100%;"
>
<el-table-column
v-for="(item,index) in columns"
:key="index"
:prop="item.prop"
:label="item.label"
align="center"
/>
</el-table>
<pagination
:module="user"
@get-data="getData"
/>
</div>
</template>
<script>
import Pagination from "@/common/components/Pagination";
import { mapActions, mapState } from "vuex";
export default {
components: {
Pagination,
},
data: () => ({
columns: [
{
prop: "name",
label: "姓名"
},
{
prop: "性別",
label: "sex"
},
{
prop: "年齡",
label: "age"
},
]
}),
created() {
this.getData();
},
methods: {
...mapActions({
getData : "getUser",
})
},
computed: {
...mapState(["user"])
}
};
</script>
複製程式碼
後記
將一些常用的功能抽象出來,打造一個自己的工具庫,從而使開發效率更高。
最後,貼上剛放假時立的 Flag:寒假待寫文章。
最後的最後,安利一下文章開頭說的專案:清技背單詞,上面的程式碼就是從這個專案中copy
出來後略作修改的。
感謝觀看,希望我的文章能對您有一些幫助!