前言
在Vue项目中,偶尔会遇到一些需求,需要前端实现分页。如果服务端一次性返回所有数据,由前端实现分页,那么这样的分页称为静态分页。本示例使用Vue2写法实现,为的是照顾还没会Vue3写法的童鞋,另外Vue3支持Vue2写法,若想改为Vue3+语法糖等其它写法,自行改改即可。
一、示例代码
(1)/src/views/Example/StaticPager/index.vue
<template>
<div class="index">
<div class="index-head">
<el-form :inline="true" style="display: flex">
<div class="index-head-left">
<el-form-item>
<el-input
size="small"
style="width: 200px"
spellcheck="false"
clearable
v-model="tableData.keyWord"
placeholder="请输入搜索关键字"
@keyup.enter="handleQueryTableData($event)"
>
<template #prefix>
<el-icon style="cursor: pointer">
<Search />
</el-icon>
</template>
</el-input>
</el-form-item>
</div>
<div class="index-head-right">
<el-form-item>
<el-button size="small" type="">
<el-icon :size="14" style="margin-right: 5px"><Download /></el-icon>
<small>导出 Excel</small>
</el-button>
</el-form-item>
</div>
</el-form>
</div>
<div class="index-body">
<div class="index-table-container">
<el-table
border
size="small"
row-key="id"
ref="tableRef"
height="100%"
:data="computedTableData.slice((tableData.pageNumber - 1) * tableData.pageSize, tableData.pageNumber * tableData.pageSize)"
:row-style="{
height:'35px'
}"
:cell-style="{
padding:'0px'
}"
highlight-current-row
>
<el-table-column prop="id" label="ID" width="100" align="center" />
<el-table-column prop="title" label="名称" width="auto" align="center" show-overflow-tooltip>
<template #default="scope">
<p class="table-container-td-title">{
{ scope.row.title }}</p>
</template>
</el-table-column>
<el-table-column label="操作" width="80" align="center">
<template #default="scope">
<el-tooltip
effect="dark"
content="复制"
placement="top"
:enterable="false"
:hide-after="0"
>
<el-icon :size="15" style="color: #5e7ce0; margin-right: 10px; cursor: pointer" @click="handleCopyclick(scope.$index, scope.row)">
<DocumentCopy />
</el-icon>
</el-tooltip>
<el-tooltip
effect="dark"
content="移除"
placement="top"
:enterable="false"
:hide-after="0"
>
<el-icon :size="15" style="color: #f56c6c; cursor: pointer" @click="handleDeleteclick(scope.row)">
<Delete />
</el-icon>
</el-tooltip>
</template>
</el-table-column>
<template #empty v-if="computedTableData.length == 0">
<div style="font-size: 40px">
<svg viewBox="0 0 1024 1024" width="1em" height="1em" fill="currentColor">
<path
d="M99.096 315.634s-82.58-64.032-82.58-132.13c0-66.064 33.032-165.162 148.646-148.646 83.37 11.91 99.096 165.162 99.096 165.162l-165.162 115.614zM924.906 315.634s82.58-64.032 82.58-132.13c0-66.064-33.032-165.162-148.646-148.646-83.37 11.91-99.096 165.162-99.096 165.162l165.162 115.614z"
fill="#6B676E"
p-id="1143"
/>
<path
d="M1024 561.548c0 264.526-229.23 429.42-512.002 429.42S0 826.076 0 561.548 283.96 66.064 512.002 66.064 1024 297.022 1024 561.548z"
fill="#FFEBD2"
p-id="1144"
/>
<path
d="M330.324 842.126c0 82.096 81.34 148.646 181.678 148.646s181.678-66.55 181.678-148.646H330.324z"
fill="#E9D7C3"
p-id="1145"
/>
<path
d="M644.13 611.098C594.582 528.516 561.55 512 512.002 512c-49.548 0-82.58 16.516-132.13 99.096-42.488 70.814-78.73 211.264-49.548 247.742 66.064 82.58 165.162 33.032 181.678 33.032 16.516 0 115.614 49.548 181.678-33.032 29.18-36.476-7.064-176.93-49.55-247.74z"
fill="#FFFFFF"
p-id="1146"
/>
<path
d="M611.098 495.484c0-45.608 36.974-82.58 82.58-82.58 49.548 0 198.194 99.098 198.194 165.162s-79.934 144.904-148.646 99.096c-49.548-33.032-132.128-148.646-132.128-181.678zM412.904 495.484c0-45.608-36.974-82.58-82.58-82.58-49.548 0-198.194 99.098-198.194 165.162s79.934 144.904 148.646 99.096c49.548-33.032 132.128-148.646 132.128-181.678z"
fill="#6B676E"
p-id="1147"
/>
<path
d="M512.002 726.622c-30.06 0-115.614 5.668-115.614 33.032 0 49.638 105.484 85.24 115.614 82.58 10.128 2.66 115.614-32.944 115.614-82.58-0.002-27.366-85.556-33.032-115.614-33.032z"
fill="#464655"
p-id="1148"
/>
<path
d="M330.324 495.484m-33.032 0a33.032 33.032 0 1 0 66.064 0 33.032 33.032 0 1 0-66.064 0Z"
fill="#464655"
p-id="1149"
/>
<path
d="M693.678 495.484m-33.032 0a33.032 33.032 0 1 0 66.064 0 33.032 33.032 0 1 0-66.064 0Z"
fill="#464655"
p-id="1150"
/>
</svg>
<p style="margin: 0; padding: 0; line-height: 13px; font-size: 13px;">暂无数据 ~</p>
</div>
</template>
</el-table>
</div>
<div class="index-pager-container">
<el-pagination
small
background
layout="total, sizes, prev, pager, next, jumper"
:current-page="tableData.pageNumber"
:page-size="tableData.pageSize"
:page-sizes="[10, 15, 20, 30, 50]"
:total="computedTableData.length"
:pager-count="5"
@current-change="handleCurrentChange"
@size-change="handleSizeChange"
>
</el-pagination>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
// 表格数据
tableData: {
keyWord: '', // 搜索关键字
list: [
{
'id': 1, 'title': '苹果'},
{
'id': 2, 'title': '香蕉'},
{
'id': 3, 'title': '葡萄'},
{
'id': 4, 'title': '雪梨'},
{
'id': 5, 'title': '橙子'},
{
'id': 6, 'title': '西瓜'},
{
'id': 7, 'title': '木瓜'},
{
'id': 8, 'title': '杨桃'},
{
'id': 9, 'title': '桃子'},
{
'id': 10, 'title': '芒果'},
{
'id': 11, 'title': '榴莲'},
{
'id': 12, 'title': '山竹'},
], // 列表
selectedList: [], // 已选列表
pageNumber: 1, // 当前页
pageSize: 10, // 页码大小
},
}
},
computed: {
/**
* 计算后的表格数据列表
*/
computedTableData () {
const search = this.tableData.keyWord
if (search) {
return this.tableData.list.filter(item => {
console.log('item =>', item)
return Object.keys(item).some(key => {
console.log('key =>', key)
// return String(item[key]).indexOf(search) > -1
return String(item.title).indexOf(search) > -1
})
})
} else {
return this.tableData.list
}
}
},
methods: {
/**
* 表格当前页句柄方法
*/
handleCurrentChange: function(pageNumber) {
this.tableData.pageNumber = pageNumber
},
/**
* 表格页码大小句柄方法
*/
handleSizeChange: function(pageSize) {
this.tableData.pageNumber = 1
this.tableData.pageSize = pageSize
},
/**
* 表格查询句柄方法
*/
handleQueryTableData() {
this.tableData.pageNumber = 1
},
/**
* 复制句柄方法
*/
handleCopyclick(index, row) {
const title = row.title
const inputElement = document.createElement('input')
inputElement.value = title
document.body.appendChild(inputElement)
inputElement.select()
document.execCommand('Copy')
inputElement.remove()
this.$message({
message: '复制 ' + title + ' 完成', type: 'success', duration: 1000 })
},
/**
* 删除句柄方法
*/
handleDeleteclick(row) {
const index = this.tableData.list.findIndex(
(item) => item.id === row.id
)
if (index != -1) {
this.tableData.list.splice(index, 1)
}
const title = row.title
this.$message({
message: '移除 ' + title + ' 完成', type: 'success', duration: 1000 })
},
}
}
</script>
<style lang="less" scoped>
.index {
display: flex;
flex-direction: column;
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
background-color: #d9e7ff;
:deep(.index-head) {
display: flex;
flex-direction: row;
background-color: #ffffff;
box-shadow: 0 3px 3px #c0d2f1;
.el-form {
display: flex;
width: 100%;
height: 100%;
.index-head-left {
flex: 1;
padding: 7px 0 0 7px;
.el-form-item {
margin-right: 7px;
margin-bottom: 7px;
.el-form-item__content {
line-height: unset;
.el-radio-group {
margin-left: 0;
}
}
}
}
.index-head-right {
padding: 7px 7px 0 0;
.el-form-item {
display: inline-flex;
margin: 0 0 7px 7px;
.el-form-item__content {
align-items: center;
}
}
}
}
}
:deep(.index-body) {
flex: 1;
display: flex;
flex-direction: column;
margin: 7px;
overflow: hidden;
.index-table-container {
flex: 1;
position: relative;
background-color: #ffffff;
overflow: hidden;
.el-table {
th .cell {
color: #000;
font-weight: normal;
font-size: 13px;
}
td {
padding: 2.5px 0;
.cell {
// color: #000;
font-size: 13px;
padding: 0 8px;
}
}
}
}
.index-pager-container {
position: relative;
width: 100%;
height: 26px;
padding: 7px 0;
background-color: #fff;
.el-pagination {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: 0 auto;
width: fit-content;
.btn-prev, .btn-next, .el-pager li {
border: 1px solid #dcdfe6;
}
.el-pager li.is-active {
border-color: #5e7ce0;
}
}
}
}
}
</style>