• 使用ElementPlus实现内嵌表格和内嵌分页


    前言

    有时遇到这样的需求,就是在表格里面嵌入一个表格,以及要求带有分页,这样在ElementPlus中很好实现。以下使用Vue2语法实现一个简单例子,毕竟Vue3兼容Vue2语法,若想要Vue3版本例子,简单改改就OK了。

    一、示例代码

    (1)/src/views/Example/InlineTable/index.vue

    1. <template>
    2. <div class="index" v-loading="elementLoading" element-loading-text="数据正在加载中...">
    3. <div class="outer-table-container">
    4. <el-table
    5. border
    6. size="small"
    7. row-key="id"
    8. ref="outerTableRef"
    9. height="100%"
    10. highlight-current-row
    11. :data="outerData.list"
    12. :expand-row-keys="outerData.expandedKeys"
    13. @expand-change="handleOuterDataExpandChange"
    14. >
    15. <el-table-column fixed prop="id" label="游戏服务器ID" width="200" align="center">
    16. <template #default="scope">
    17. <p>{{ scope.row.id }}p>
    18. template>
    19. el-table-column>
    20. <el-table-column fixed prop="id" label="玩家列表" type="expand" width="200" align="center">
    21. <template #default="scope">
    22. <div class="outer-table-container-td__playerList" v-loading="scope.row.loading">
    23. <div class="inner-table-container">
    24. <el-table
    25. border
    26. size="small"
    27. row-key="id"
    28. height="100%"
    29. highlight-current-row
    30. :data="scope.row.list"
    31. >
    32. <el-table-column fixed prop="id" label="玩家ID" width="200" align="center">
    33. <template #default="scope">
    34. <p>{{ scope.row.id }}p>
    35. template>
    36. el-table-column>
    37. <el-table-column prop="power" label="玩家战力" width="auto" align="center" show-overflow-tooltip>
    38. <template #default="scope">
    39. <p style="text-align: left; text-indent: 10px; margin: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">{{ scope.row.power }}p>
    40. template>
    41. el-table-column>
    42. <el-table-column fixed="right" label="操作" align="center" width="150">
    43. <template #default="scope">
    44. <div class="inner-table-container-td__operation">
    45. <el-row>
    46. <el-col :span="24">
    47. <el-tooltip effect="dark" content="查看详情" placement="top" :enterable="false" :hide-after="0">
    48. <el-button size="small" type="" style="border: unset" plain circle @click="
    49. () => {
    50. log('查看详情 =>', scope.row)
    51. }
    52. ">
    53. <el-icon :size="16"><View />el-icon>
    54. el-button>
    55. el-tooltip>
    56. el-col>
    57. el-row>
    58. div>
    59. template>
    60. el-table-column>
    61. el-table>
    62. div>
    63. <div class="inner-pagger-container">
    64. <el-pagination
    65. v-if="scope.row.total > 0"
    66. small
    67. background
    68. v-model:current-page="scope.row.pageNumber"
    69. v-model:page-size="scope.row.pageSize"
    70. :total="scope.row.total"
    71. :page-sizes="[10, 20, 50, 100]"
    72. layout="total, sizes, prev, pager, next, jumper"
    73. @size-change="handleInnerTableSizeChange(scope.row)"
    74. @current-change="handleInnerTableCurrentChange(scope.row)"
    75. />
    76. div>
    77. div>
    78. template>
    79. el-table-column>
    80. <el-table-column prop="host" label="游戏服务器名称" width="auto" min-width="400" align="center" show-overflow-tooltip>
    81. <template #default="scope">
    82. <p class="outer-table-container-td__name">{{ scope.row.host }}p>
    83. template>
    84. el-table-column>
    85. <el-table-column label="创建时间" width="400" align="center">
    86. <template #default="scope">
    87. <div>{{ scope.row.createTime ? scope.row.createTime : '-' }}div>
    88. template>
    89. el-table-column>
    90. el-table>
    91. div>
    92. <div class="outer-pagger-container">
    93. <el-pagination
    94. small
    95. background
    96. :current-page="outerData.pageNumber"
    97. :page-size="outerData.pageSize"
    98. :page-sizes="[20, 30, 50, 100]"
    99. :total="outerData.total"
    100. layout="total, sizes, prev, pager, next, jumper"
    101. @size-change="handleOuterTableSizeChange"
    102. @current-change="handleOuterTableCurrentChange"
    103. >
    104. el-pagination>
    105. div>
    106. div>
    107. template>
    108. <script>
    109. export default {
    110. data: () => ({
    111. // 加载标志
    112. elementLoading: true,
    113. // 外层数据
    114. outerData: {
    115. list: [], // 列表
    116. selectedList: [], // 已选列表
    117. expandedKeys: [], // 已展开键集合
    118. expandedList: [], // 已展开列表
    119. total: 521, // 总数
    120. pageNumber: 1, // 当前页
    121. pageSize: 20, // 页码大小
    122. },
    123. // 打印日志
    124. log: console.log
    125. }),
    126. created() {
    127. this.init()
    128. },
    129. mounted() {
    130. },
    131. methods: {
    132. // ---- ---- ---- ---- ^ 事件调用方法 ---- ---- ---- ----
    133. /**
    134. * 初始化外层表格
    135. */
    136. init() {
    137. const list = []
    138. for (let i = 0; i < this.outerData.pageSize; i++) {
    139. const number = parseInt(Math.random() * 10000) + i
    140. const row = {
    141. id: number,
    142. host: `游戏服务器 - ${number}`,
    143. createTime: new Date()
    144. }
    145. list.push(row)
    146. }
    147. this.outerData.list = list
    148. this.outerData.total = this.outerData.total
    149. this.elementLoading = false
    150. },
    151. /**
    152. * 外层表格 - 页码改变方法
    153. */
    154. handleOuterTableSizeChange(val) {
    155. this.elementLoading = true
    156. this.outerData.pageNumber = 1
    157. this.outerData.pageSize = val
    158. const frontRecords = this.outerData.pageSize * (this.outerData.pageNumber - 1)
    159. const remainRecords = this.outerData.total - frontRecords
    160. let list = []
    161. if (remainRecords >= this.outerData.pageSize) {
    162. for (let i = 0; i < this.outerData.pageSize; i++) {
    163. const number = parseInt(Math.random() * 10000) + i
    164. const row = {
    165. id: number,
    166. host: `游戏服务器 - ${number}`,
    167. createTime: new Date()
    168. }
    169. list.push(row)
    170. }
    171. } else {
    172. for (let i = 0; i < remainRecords; i++) {
    173. const number = parseInt(Math.random() * 10000) + i
    174. const row = {
    175. id: number,
    176. host: `游戏服务器 - ${number}`,
    177. createTime: new Date()
    178. }
    179. list.push(row)
    180. }
    181. }
    182. setTimeout(() => {
    183. this.outerData.list = list
    184. this.outerData.total = this.outerData.total
    185. this.elementLoading = false
    186. }, 200)
    187. },
    188. /**
    189. * 外层表格 - 当前页改变方法
    190. */
    191. handleOuterTableCurrentChange(val) {
    192. this.elementLoading = true
    193. this.outerData.pageNumber = val
    194. const frontRecords = this.outerData.pageSize * (this.outerData.pageNumber - 1)
    195. const remainRecords = this.outerData.total - frontRecords
    196. let list = []
    197. if (remainRecords >= this.outerData.pageSize) {
    198. for (let i = 0; i < this.outerData.pageSize; i++) {
    199. const number = parseInt(Math.random() * 10000) + i
    200. const row = {
    201. id: number,
    202. host: `游戏服务器 - ${number}`,
    203. createTime: new Date()
    204. }
    205. list.push(row)
    206. }
    207. } else {
    208. for (let i = 0; i < remainRecords; i++) {
    209. const number = parseInt(Math.random() * 10000) + i
    210. const row = {
    211. id: number,
    212. host: `游戏服务器 - ${number}`,
    213. createTime: new Date()
    214. }
    215. list.push(row)
    216. }
    217. }
    218. setTimeout(() => {
    219. this.outerData.list = list
    220. this.outerData.total = this.outerData.total
    221. this.elementLoading = false
    222. }, 200)
    223. },
    224. /**
    225. * 外层表格 - 展开/收起某一行事件句柄方法
    226. */
    227. async handleOuterDataExpandChange(row, expandedRows) {
    228. this.outerData.expandedList = expandedRows
    229. const index = this.outerData.expandedList.findIndex((item) => item.id === row.id)
    230. if (index != -1) {
    231. // 展开
    232. this.getPlayerList(row)
    233. } else {
    234. // 收起
    235. row.loading = true
    236. }
    237. },
    238. /**
    239. * 根据游戏服务器获取玩家列表
    240. */
    241. async getPlayerList(row) {
    242. for (let vo of this.outerData.list) {
    243. // 匹配游戏服务器
    244. if (vo.id == row.id) {
    245. vo.loading = false
    246. vo.list = [] // 列表
    247. vo.total = 25 // 总数
    248. vo.pageNumber = 1 // 当前页
    249. vo.pageSize = 10 // 页码大小
    250. const list = []
    251. for (let i = 0; i < vo.pageSize; i++) {
    252. const number = parseInt(Math.random() * 100000000) + i
    253. const row = {
    254. id: number,
    255. power: Math.pow(number, 5),
    256. }
    257. list.push(row)
    258. }
    259. vo.list = list
    260. }
    261. }
    262. },
    263. /**
    264. * 内嵌表格 - 页码改变方法
    265. */
    266. handleInnerTableSizeChange(row) {
    267. row.loading = true
    268. row.pageNumber = 1
    269. const frontRecords = row.pageSize * (row.pageNumber - 1)
    270. const remainRecords = row.total - frontRecords
    271. let list = []
    272. if (remainRecords >= row.pageSize) {
    273. for (let i = 0; i < row.pageSize; i++) {
    274. const number = parseInt(Math.random() * 100000000) + i
    275. const row = {
    276. id: number,
    277. power: Math.pow(number, 5),
    278. }
    279. list.push(row)
    280. }
    281. } else {
    282. for (let i = 0; i < remainRecords; i++) {
    283. const number = parseInt(Math.random() * 100000000) + i
    284. const row = {
    285. id: number,
    286. power: Math.pow(number, 5),
    287. }
    288. list.push(row)
    289. }
    290. }
    291. setTimeout(() => {
    292. row.list = list
    293. row.total = row.total
    294. row.loading = false
    295. }, 200)
    296. },
    297. /**
    298. * 内嵌表格 - 当前页改变方法
    299. */
    300. handleInnerTableCurrentChange(row) {
    301. row.loading = true
    302. const frontRecords = row.pageSize * (row.pageNumber - 1)
    303. const remainRecords = row.total - frontRecords
    304. let list = []
    305. if (remainRecords >= row.pageSize) {
    306. for (let i = 0; i < row.pageSize; i++) {
    307. const number = parseInt(Math.random() * 100000000) + i
    308. const row = {
    309. id: number,
    310. power: Math.pow(number, 5),
    311. }
    312. list.push(row)
    313. }
    314. } else {
    315. for (let i = 0; i < remainRecords; i++) {
    316. const number = parseInt(Math.random() * 100000000) + i
    317. const row = {
    318. id: number,
    319. power: Math.pow(number, 5),
    320. }
    321. list.push(row)
    322. }
    323. }
    324. setTimeout(() => {
    325. row.list = list
    326. row.total = row.total
    327. row.loading = false
    328. }, 200)
    329. },
    330. }
    331. }
    332. script>
    333. <style lang="less" scoped>
    334. .index {
    335. display: flex;
    336. flex-direction: column;
    337. width: 100%;
    338. height: 100%;
    339. overflow: hidden;
    340. // ---- ---- ---- ---- ^ 外层表格 样式 ---- ---- ---- ----
    341. :deep(.outer-table-container) {
    342. flex: 1;
    343. position: relative;
    344. overflow: hidden;
    345. .el-table {
    346. th {
    347. .cell {
    348. color: #000;
    349. font-weight: normal;
    350. font-size: 13px;
    351. }
    352. }
    353. td {
    354. padding: 2.5px 0;
    355. .cell {
    356. // color: #000;
    357. font-size: 13px;
    358. padding: 0;
    359. }
    360. }
    361. .outer-table-container-td__playerList {
    362. height: auto;
    363. overflow: auto;
    364. padding: 4px 7px;
    365. /* ^ 内嵌表格 */
    366. .inner-table-container {
    367. position: relative;
    368. overflow: hidden;
    369. .el-table {
    370. th {
    371. .cell {
    372. color: #000;
    373. font-weight: normal;
    374. font-size: 13px;
    375. }
    376. }
    377. td {
    378. padding: 2.5px 0;
    379. .cell {
    380. // color: #000;
    381. font-size: 13px;
    382. padding: 0;
    383. }
    384. }
    385. .el-table__cell {
    386. // background-color: #f8f8f8;
    387. }
    388. }
    389. /* 操作 */
    390. .inner-table-container-td__operation {
    391. .el-button {
    392. position: relative;
    393. margin: 0px 1px;
    394. }
    395. }
    396. /* / 操作 */
    397. }
    398. /* / 内嵌表格 */
    399. /* ^ 内嵌分页 */
    400. .inner-pagger-container {
    401. position: relative;
    402. width: 100%;
    403. height: 26px;
    404. margin-top: 7px;
    405. .el-pagination {
    406. position: absolute;
    407. top: 0;
    408. // left: 0;
    409. right: 0;
    410. bottom: 0;
    411. margin: 0 auto;
    412. width: fit-content;
    413. .btn-prev, .btn-next, .el-pager li {
    414. border: 1px solid #dcdfe6;
    415. }
    416. .el-pager li.is-active {
    417. border-color: #5e7ce0;
    418. }
    419. }
    420. }
    421. /* / 内嵌分页 */
    422. }
    423. /* 操作 */
    424. .operation {
    425. .el-button {
    426. position: relative;
    427. margin: 0px 1px;
    428. }
    429. }
    430. /* / 操作 */
    431. }
    432. }
    433. // ---- ---- ---- ---- / 外层表格 样式 ---- ---- ---- ----
    434. // ---- ---- ---- ---- ^ 外层分页 样式 ---- ---- ---- ----
    435. :deep(.outer-pagger-container) {
    436. padding: 7px 0;
    437. width: 100%;
    438. height: 26px;
    439. position: relative;
    440. .el-pagination {
    441. position: absolute;
    442. top: 0;
    443. left: 0;
    444. right: 0;
    445. bottom: 0;
    446. margin: 0 auto;
    447. width: fit-content;
    448. .btn-prev, .btn-next, .el-pager li {
    449. border: 1px solid #dcdfe6;
    450. }
    451. .el-pager li.is-active {
    452. border-color: #5e7ce0;
    453. }
    454. }
    455. }
    456. // ---- ---- ---- ---- / 外层分页 样式 ---- ---- ---- ----
    457. }
    458. style>

    二、运行效果

  • 相关阅读:
    c++可变参数模板
    【实用小工具】一键分离音频中的纯人声~
    yolov5之魔化修改
    【mindspore】【训练】训练过程内存占用大
    动态规划求数组中相邻两数的最小差值( 即相差的绝对值 ) java 实现
    拷贝加密U盘文件
    什么是glTF?glTF详解
    Google发布Genie硬杠Sora:通过大量无监督视频训练最终生成可交互虚拟世界
    Asp.Net 6.0 集成 AutoMapper 初入
    黄金票据和白银票据
  • 原文地址:https://blog.csdn.net/Cai181191/article/details/132884385