Prefacio
A veces nos encontramos con un requisito de este tipo, que es incrustar una tabla dentro de la tabla y requerir paginación, lo cual es fácil de implementar en ElementPlus. A continuación se utiliza la sintaxis de Vue2 para implementar un ejemplo simple. Después de todo, Vue3 es compatible con la sintaxis de Vue2. Si desea un ejemplo de la versión de Vue3, simplemente cámbielo y estará bien.
1. Código de muestra
(1)/src/views/Example/InlineTable/index.vue
<template>
<div class="index" v-loading="elementLoading" element-loading-text="数据正在加载中...">
<!-- 外层表格 -->
<div class="outer-table-container">
<el-table
border
size="small"
row-key="id"
ref="outerTableRef"
height="100%"
highlight-current-row
:data="outerData.list"
:expand-row-keys="outerData.expandedKeys"
@expand-change="handleOuterDataExpandChange"
>
<el-table-column fixed prop="id" label="游戏服务器ID" width="200" align="center">
<template #default="scope">
<p>{
{ scope.row.id }}</p>
</template>
</el-table-column>
<el-table-column fixed prop="id" label="玩家列表" type="expand" width="200" align="center">
<template #default="scope">
<div class="outer-table-container-td__playerList" v-loading="scope.row.loading">
<!-- ^ 内嵌表格 -->
<div class="inner-table-container">
<el-table
border
size="small"
row-key="id"
height="100%"
highlight-current-row
:data="scope.row.list"
>
<el-table-column fixed prop="id" label="玩家ID" width="200" align="center">
<template #default="scope">
<p>{
{ scope.row.id }}</p>
</template>
</el-table-column>
<el-table-column prop="power" label="玩家战力" width="auto" align="center" show-overflow-tooltip>
<template #default="scope">
<p style="text-align: left; text-indent: 10px; margin: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">{
{ scope.row.power }}</p>
</template>
</el-table-column>
<el-table-column fixed="right" label="操作" align="center" width="150">
<template #default="scope">
<div class="inner-table-container-td__operation">
<el-row>
<el-col :span="24">
<!-- ^ 查看详情 -->
<el-tooltip effect="dark" content="查看详情" placement="top" :enterable="false" :hide-after="0">
<el-button size="small" type="" style="border: unset" plain circle @click="
() => {
log('查看详情 =>', scope.row)
}
">
<el-icon :size="16"><View /></el-icon>
</el-button>
</el-tooltip>
<!-- / 查看详情 -->
</el-col>
</el-row>
</div>
</template>
</el-table-column>
</el-table>
</div>
<!-- / 内嵌表格 -->
<!-- ^ 内嵌分页 -->
<div class="inner-pagger-container">
<el-pagination
v-if="scope.row.total > 0"
small
background
v-model:current-page="scope.row.pageNumber"
v-model:page-size="scope.row.pageSize"
:total="scope.row.total"
:page-sizes="[10, 20, 50, 100]"
layout="total, sizes, prev, pager, next, jumper"
@size-change="handleInnerTableSizeChange(scope.row)"
@current-change="handleInnerTableCurrentChange(scope.row)"
/>
</div>
</div>
</template>
</el-table-column>
<el-table-column prop="host" label="游戏服务器名称" width="auto" min-width="400" align="center" show-overflow-tooltip>
<template #default="scope">
<p class="outer-table-container-td__name">{
{ scope.row.host }}</p>
</template>
</el-table-column>
<el-table-column label="创建时间" width="400" align="center">
<template #default="scope">
<div>{
{ scope.row.createTime ? scope.row.createTime : '-' }}</div>
</template>
</el-table-column>
</el-table>
</div>
<!-- / 外层表格 -->
<!-- 外层分页 -->
<div class="outer-pagger-container">
<el-pagination
small
background
:current-page="outerData.pageNumber"
:page-size="outerData.pageSize"
:page-sizes="[20, 30, 50, 100]"
:total="outerData.total"
layout="total, sizes, prev, pager, next, jumper"
@size-change="handleOuterTableSizeChange"
@current-change="handleOuterTableCurrentChange"
>
</el-pagination>
</div>
<!-- / 外层分页 -->
</div>
</template>
<script>
export default {
data: () => ({
// 加载标志
elementLoading: true,
// 外层数据
outerData: {
list: [], // 列表
selectedList: [], // 已选列表
expandedKeys: [], // 已展开键集合
expandedList: [], // 已展开列表
total: 521, // 总数
pageNumber: 1, // 当前页
pageSize: 20, // 页码大小
},
// 打印日志
log: console.log
}),
created() {
this.init()
},
mounted() {
},
methods: {
// ---- ---- ---- ---- ^ 事件调用方法 ---- ---- ---- ----
/**
* 初始化外层表格
*/
init() {
const list = []
for (let i = 0; i < this.outerData.pageSize; i++) {
const number = parseInt(Math.random() * 10000) + i
const row = {
id: number,
host: `游戏服务器 - ${number}`,
createTime: new Date()
}
list.push(row)
}
this.outerData.list = list
this.outerData.total = this.outerData.total
this.elementLoading = false
},
/**
* 外层表格 - 页码改变方法
*/
handleOuterTableSizeChange(val) {
this.elementLoading = true
this.outerData.pageNumber = 1
this.outerData.pageSize = val
const frontRecords = this.outerData.pageSize * (this.outerData.pageNumber - 1)
const remainRecords = this.outerData.total - frontRecords
let list = []
if (remainRecords >= this.outerData.pageSize) {
for (let i = 0; i < this.outerData.pageSize; i++) {
const number = parseInt(Math.random() * 10000) + i
const row = {
id: number,
host: `游戏服务器 - ${number}`,
createTime: new Date()
}
list.push(row)
}
} else {
for (let i = 0; i < remainRecords; i++) {
const number = parseInt(Math.random() * 10000) + i
const row = {
id: number,
host: `游戏服务器 - ${number}`,
createTime: new Date()
}
list.push(row)
}
}
setTimeout(() => {
this.outerData.list = list
this.outerData.total = this.outerData.total
this.elementLoading = false
}, 200)
},
/**
* 外层表格 - 当前页改变方法
*/
handleOuterTableCurrentChange(val) {
this.elementLoading = true
this.outerData.pageNumber = val
const frontRecords = this.outerData.pageSize * (this.outerData.pageNumber - 1)
const remainRecords = this.outerData.total - frontRecords
let list = []
if (remainRecords >= this.outerData.pageSize) {
for (let i = 0; i < this.outerData.pageSize; i++) {
const number = parseInt(Math.random() * 10000) + i
const row = {
id: number,
host: `游戏服务器 - ${number}`,
createTime: new Date()
}
list.push(row)
}
} else {
for (let i = 0; i < remainRecords; i++) {
const number = parseInt(Math.random() * 10000) + i
const row = {
id: number,
host: `游戏服务器 - ${number}`,
createTime: new Date()
}
list.push(row)
}
}
setTimeout(() => {
this.outerData.list = list
this.outerData.total = this.outerData.total
this.elementLoading = false
}, 200)
},
/**
* 外层表格 - 展开/收起某一行事件句柄方法
*/
async handleOuterDataExpandChange(row, expandedRows) {
this.outerData.expandedList = expandedRows
const index = this.outerData.expandedList.findIndex((item) => item.id === row.id)
if (index != -1) {
// 展开
this.getPlayerList(row)
} else {
// 收起
row.loading = true
}
},
/**
* 根据游戏服务器获取玩家列表
*/
async getPlayerList(row) {
for (let vo of this.outerData.list) {
// 匹配游戏服务器
if (vo.id == row.id) {
vo.loading = false
vo.list = [] // 列表
vo.total = 25 // 总数
vo.pageNumber = 1 // 当前页
vo.pageSize = 10 // 页码大小
const list = []
for (let i = 0; i < vo.pageSize; i++) {
const number = parseInt(Math.random() * 100000000) + i
const row = {
id: number,
power: Math.pow(number, 5),
}
list.push(row)
}
vo.list = list
}
}
},
/**
* 内嵌表格 - 页码改变方法
*/
handleInnerTableSizeChange(row) {
row.loading = true
row.pageNumber = 1
const frontRecords = row.pageSize * (row.pageNumber - 1)
const remainRecords = row.total - frontRecords
let list = []
if (remainRecords >= row.pageSize) {
for (let i = 0; i < row.pageSize; i++) {
const number = parseInt(Math.random() * 100000000) + i
const row = {
id: number,
power: Math.pow(number, 5),
}
list.push(row)
}
} else {
for (let i = 0; i < remainRecords; i++) {
const number = parseInt(Math.random() * 100000000) + i
const row = {
id: number,
power: Math.pow(number, 5),
}
list.push(row)
}
}
setTimeout(() => {
row.list = list
row.total = row.total
row.loading = false
}, 200)
},
/**
* 内嵌表格 - 当前页改变方法
*/
handleInnerTableCurrentChange(row) {
row.loading = true
const frontRecords = row.pageSize * (row.pageNumber - 1)
const remainRecords = row.total - frontRecords
let list = []
if (remainRecords >= row.pageSize) {
for (let i = 0; i < row.pageSize; i++) {
const number = parseInt(Math.random() * 100000000) + i
const row = {
id: number,
power: Math.pow(number, 5),
}
list.push(row)
}
} else {
for (let i = 0; i < remainRecords; i++) {
const number = parseInt(Math.random() * 100000000) + i
const row = {
id: number,
power: Math.pow(number, 5),
}
list.push(row)
}
}
setTimeout(() => {
row.list = list
row.total = row.total
row.loading = false
}, 200)
},
}
}
</script>
<style lang="less" scoped>
.index {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
overflow: hidden;
// ---- ---- ---- ---- ^ 外层表格 样式 ---- ---- ---- ----
:deep(.outer-table-container) {
flex: 1;
position: relative;
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;
}
}
.outer-table-container-td__playerList {
height: auto;
overflow: auto;
padding: 4px 7px;
/* ^ 内嵌表格 */
.inner-table-container {
position: relative;
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;
}
}
.el-table__cell {
// background-color: #f8f8f8;
}
}
/* 操作 */
.inner-table-container-td__operation {
.el-button {
position: relative;
margin: 0px 1px;
}
}
/* / 操作 */
}
/* / 内嵌表格 */
/* ^ 内嵌分页 */
.inner-pagger-container {
position: relative;
width: 100%;
height: 26px;
margin-top: 7px;
.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;
}
}
}
/* / 内嵌分页 */
}
/* 操作 */
.operation {
.el-button {
position: relative;
margin: 0px 1px;
}
}
/* / 操作 */
}
}
// ---- ---- ---- ---- / 外层表格 样式 ---- ---- ---- ----
// ---- ---- ---- ---- ^ 外层分页 样式 ---- ---- ---- ----
:deep(.outer-pagger-container) {
padding: 7px 0;
width: 100%;
height: 26px;
position: relative;
.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>