前言
有时遇到这样的需求,就是在表格里面嵌入一个表格,以及要求带有分页,这样在ElementPlus中很好实现。以下使用Vue2语法实现一个简单例子,毕竟Vue3兼容Vue2语法,若想要Vue3版本例子,简单改改就OK了。
一、示例代码
(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>