elementplus實(shí)現(xiàn)多級(jí)表格(最后一級(jí)展示圖片)
想要實(shí)現(xiàn)的效果
總共四級(jí) 前三級(jí)是表格 第四級(jí)使用圖片展示; 看了一下官網(wǎng) 計(jì)劃使用官網(wǎng)的樹(shù)形結(jié)構(gòu), 但是發(fā)現(xiàn)并不能滿足最后一個(gè)是圖片形式的展示
最后利用了表格的expand;
在過(guò)程中主要需要解決的問(wèn)題有:vue3 遞歸使用組件;遞歸處理數(shù)據(jù);展開(kāi)全部級(jí)。
遞歸處理數(shù)據(jù)
首先需要處理一下數(shù)據(jù),把他們弄成字段一致的,如果后端處理過(guò),前端也會(huì)需要處理一下,用于前端自己新增使用的字段 ,我這邊 新增了三個(gè)字段
- disableExpand: 用于我的展開(kāi)表格 單行能不能展開(kāi)
- id: 后端沒(méi)有給id字段 用于唯一標(biāo)識(shí)
- level: 判斷當(dāng)前數(shù)據(jù)是第幾級(jí)數(shù)據(jù)
const getOverviewList = async () => { ? if (!searchParams.value.train_type_id) { ? ? return; ? } ? const resp = await Pepper.get('/api/match/detail', { ? ? params: searchParams.value ? }); ? overviewTotal.value = resp.data.list.length; ? overviewList.value = handleOverviewList(resp.data.list); }; const handleOverviewList = (data: OverviewListModel[], listLevel = 1) => { ? const result: OverviewListModel[] = data.map((item, index) => { ? ? return { ? ? ? ...item, ? ? ? // 新增字段 ? ? ? disableExpand: !!item.sub_number, ? ? ? level: listLevel, ? ? ? id: listLevel + '-' + index, ? ? ? // 處理list ? ? ? list: item.list && item.list.length ? handleOverviewList(item.list as OverviewListModel[], listLevel + 1) : [] ? ? }; ? }); ? return result; };
遞歸調(diào)用組件
因?yàn)樽侄我恢滤晕沂褂玫氖峭粋€(gè)組件,需要說(shuō)明的是 vue3使用自己組件的時(shí)候直接使用即可
在外層:傳入所有的data
<overview-table ref="overviewTableRef" :total="overviewTotal" :data="overviewList" />
在OverviewTable組件中 直接使用OverviewTable就可;下面這個(gè)包括展開(kāi)所有級(jí)的代碼
展開(kāi)所有級(jí) 利用@expand=“handleExpand” 修改expandKeys即可
<template> ? <div> ? ? <expand-table ? ? ? ref="tableRef" ? ? ? :data="data" ? ? ? :total="total" ? ? ? :pageParams="pageParams" ? ? ? v-model:expandRowKeys="expandKeys" ? ? ? v-bind="$attrs" ? ? ? @oneClick="rowClick" ? ? ? @expand="handleExpand" ? ? > ? ? ? <template #expand="{ row }"> ? ? ? ? <overview-table ? ? ? ? ? :ref="el => setOverviewDetailRef(el, row.id)" ? ? ? ? ? v-if="row.level !== 3" ? ? ? ? ? :data="row.list" ? ? ? ? ? :total="row.list.length" ? ? ? ? ? :show-header="false" ? ? ? ? ? :height="2000" ? ? ? ? ? :table-level="row.level + 1" ? ? ? ? /> ? ? ? ? <overview-table-detail ? ? ? ? ? v-else ? ? ? ? ? :data="row.list" ? ? ? ? ? @openDialog="openDialog" ? ? ? ? /> ? ? ? </template> ? ? ? <el-table-column ? ? ? ? prop="name" ? ? ? ? min-width="10%" ? ? ? ? label="數(shù)據(jù)類型" ? ? ? /> ? ? ? .... ? ? ? <el-table-column ? ? ? ? prop="sub_number" ? ? ? ? min-width="10%" ? ? ? ? label="包含下級(jí)數(shù)" ? ? ? > ? ? ? ? <template #default="{ row }"> ? ? ? ? ? <span :class="!row.sub_number ? 'no-sub' : ''">{{ row.sub_number }}</span> ? ? ? ? </template> ? ? ? </el-table-column> ? ? ? <operation-column ? ? ? ? min-width="10%" ? ? ? ? :operationOptions="operationOptions" ? ? ? /> ? ? </expand-table> ? ? <image-detail-dialog ? ? ? :showDeleteBtn="false" ? ? ? ref="imageDetailDialogRef" ? ? /> ? </div> </template> <script setup lang="ts"> import { computed, ref, inject, nextTick } from 'vue'; import ExpandTable from '@/components/table/ExpandTable.vue'; import OverviewTableDetail from './OverviewTableDetail.vue'; import ImageDetailDialog from '../../original/stop/ImageDetailDialog.vue'; import OperationColumn, { OperationOptionModel } from '@/components/table/OperationColumn.vue'; import { PageAware } from '@/model'; import { ConfigModel } from 'public/config'; import { OverviewListModel } from '@/model/registration'; import { PhotoListModel } from '@/model/original'; const props = withDefaults( ? defineProps<{ ? ? data: OverviewListModel[]; ? ? total: number; ? ? tableLevel?: number; ? }>(), ? { ? ? data: () => [], ? ? tableLevel: 1 ? } ); const pageParams = ref<PageAware>({ ? page_no: 1, ? page_size: (inject('global') as ConfigModel).registration.registrationLimit }); const tableRef = ref<InstanceType<typeof ExpandTable>>(); const overviewDetailRefs = ref<any>({}); const imageDetailDialogRef = ref<InstanceType<typeof ImageDetailDialog>>(); const expandKeys = ref<string[]>([]); const operationOptions = computed<OperationOptionModel[]>(() => { ? return [ ? ? { ? ? ? icon: 'icon-upload', ? ? ? title: '上傳', ? ? ? hidden: props.tableLevel !== 1, ? ? ? onClick: () => {} ? ? }, ? ? { ? ? ? icon: 'icon-compute', ? ? ? title: '計(jì)算', ? ? ? hidden: props.tableLevel !== 2, ? ? ? disabled: (row: OverviewListModel) => { ? ? ? ? return row.state !== '待計(jì)算'; ? ? ? }, ? ? ? onClick: () => {} ? ? } ? ]; }); // 動(dòng)態(tài)ref const setOverviewDetailRef = (el: any, id: number) => { ? if (el) { ? ? overviewDetailRefs.value[id] = el; ? } }; // 打開(kāi)彈窗 const openDialog = (index: any, data: PhotoListModel[]) => { ? imageDetailDialogRef.value?.open(index, data); }; // 單擊展開(kāi)/關(guān)閉 const rowClick = (row: OverviewListModel) => { ? if (expandKeys.value.includes(row.id)) { ? ? tableRef.value?.closeRowExpansion(row); ? } else { ? ? expandKeys.value.push(row.id); ? } }; // 展開(kāi)全部 const handleExpand = (ids: number[] | string[]) => { ? // 情況1:一級(jí)全部展開(kāi) 點(diǎn)擊其他的時(shí)候 只展開(kāi)下一級(jí) ? // const handleExpand = (ids: number[] | string[], autoExpand) => { ? // autoExpand.value = autoExpandEd ? autoExpandEd : props.tableLevel === 1; ? // if (!autoExpand.value) { ? // ? return; ? // } ? // ?情況3:點(diǎn)擊一級(jí) 只展開(kāi)到三級(jí) ? // if (props.tableLevel !== 1) { ? // ? return; ? // } ? ids.forEach(async id => { ? ? await nextTick(); ? ? const stopOverviewDetailRef = overviewDetailRefs.value[id]; ? ? if (stopOverviewDetailRef) { ? ? ? await stopOverviewDetailRef?.openRowExpansion(); ? ? } ? }); }; const openRowExpansion = () => { ? //情況1:一級(jí)全部展開(kāi) 點(diǎn)擊其他的時(shí)候 只展開(kāi)下一級(jí) ? // const ids = (props.data as OverviewListModel[]).map(i => i.id); ? // handleExpand(ids, true); ? // 情況2:點(diǎn)擊任何一級(jí) 他下面的都展開(kāi) ? props.data.map(item => { ? ? if (!item.disableExpand) { ? ? ? return; ? ? } ? ? if (!expandKeys.value.includes(item.id)) { ? ? ? expandKeys.value.push(item.id); ? ? } ? }); }; const reset = () => { ? // 重新搜索的時(shí)候 關(guān)閉展開(kāi)的 ? tableRef.value?.closeAllExpand(); ? expandKeys.value = []; }; defineExpose({ ? reset, ? expandKeys, ? openRowExpansion }); </script> <style lang="scss" scoped> :deep(.el-table__expanded-cell[class*='cell']) { ? padding: 0; } :deep(.el-button + .el-button) { ? margin-left: 0; } .no-sub { ? color: #b9bdc9; } // 防止彈框樣式有問(wèn)題 :deep(.el-table .el-table__row) { ? position: relative; ? z-index: 0; } </style>
到此這篇關(guān)于elementplus 實(shí)現(xiàn)多級(jí)表格 最后一級(jí)展示圖片的文章就介紹到這了,更多相關(guān)elementplus 多級(jí)表格 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue實(shí)現(xiàn)點(diǎn)擊當(dāng)前標(biāo)簽高亮效果【推薦】
這篇文章主要介紹了vue實(shí)現(xiàn)點(diǎn)擊當(dāng)前標(biāo)簽高亮效果的思路詳解,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2018-06-06nuxt實(shí)現(xiàn)封裝axios并且獲取token
這篇文章主要介紹了nuxt實(shí)現(xiàn)封裝axios并且獲取token,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-10-10Vant中Popover氣泡彈出框位置錯(cuò)亂問(wèn)題解決
這篇文章主要為大家介紹了Vant中Popover氣泡彈出框位置錯(cuò)亂問(wèn)題解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-06-06vue如何通過(guò)button的disabled控制按鈕能否被使用
這篇文章主要介紹了vue如何通過(guò)button的disabled控制按鈕能否被使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04詳解如何在Vue項(xiàng)目中實(shí)現(xiàn)累加動(dòng)畫
這篇文章主要為大家詳細(xì)介紹了如何在你的Vue項(xiàng)目中實(shí)現(xiàn)累加動(dòng)畫,文中的示例代碼簡(jiǎn)潔易懂,具有一定的參考價(jià)值,感興趣的小伙伴可以了解一下2023-06-06