Element實現動態表格的示例代碼
【代碼背景】
有這樣一個業務需求場景,有大概十幾張表歸屬於某個類別,用戶希望在同一個頁面,通過選擇不同的查詢指標展示不同的表格,這些表的表頭樣式類似但是又不完全相同,怎麼做呢?
到目前為止所有基於Element UI的表格樣式都是直接在頁面寫死的,像官方這樣:
<el-table :data="tableData" style="width: 100%"> <el-table-column prop="date" label="日期" width="180"></el-table-column> <el-table-column prop="name" label="姓名" width="180"></el-table-column> <el-table-column prop="address" label="地址"></el-table-column> </el-table>
要解決上述問題,最簡單暴力的方式是為每個表寫一個單獨組件,然後通過select框觸發事件切換不同組件路由渲染頁面,當然這種方式很笨,也不符合代碼復用的基本原則,所以為瞭偷懶,為瞭堅守代碼復用的基本原則,開始思考有沒有更好的方式來解決這個問題。
仔細觀察這個<el-table>,表格數據是通過:data綁定的,表格頭部數據則是通過<el-table-column>標簽展示的,表頭數據是不是也可以通過某種傳參的方式結合v-for來渲染<el-table-column>的具體數據呢?在度娘的幫助下,果然有大佬已經這樣做瞭,實現瞭動態表格,參考鏈接掛在最底下瞭哦,在此特別感謝免費分享知識的大佬們,知識無價,學無止境。
現將本項目的具體實現代碼記錄如下,完善瞭一些代碼的註解,嘗試幫助理解。
【代碼實現】
#1# -> 代碼復用的基礎是你需要一個可復用的組件
在/components/Table文件夾下新建兩個組件
DynamicTable.vue
<template> <!-- 動態展示表格 --> <el-table :data="tableData" border stripe :height="height" @row-click="handleRowClick"> <!-- v-for 循環取表頭數據 --> <template v-for="item in tableHeader"> <table-column v-if="item.children && item.children.length" :key="item.id" :column-header="item" /> <el-table-column v-else :key="item.id" :label="item.label" :prop="item.prop" align="center" /> </template> </el-table> </template>
<script> import TableColumn from '@/components/Table/TableColumn' export default { name: 'DynamicTable', components: { TableColumn }, props: { // 表格的數據 tableData: { type: Array, required: true }, // 多級表頭的數據 tableHeader: { type: Array, required: true }, // 表格的高度 height: { type: String, default: '300' } }, methods: { // 行點擊事件 handleRowClick (row, column, event) { // console.log(row) // console.log(column) // console.log(event) // 通知調用父組件的row-click事件 // row作為參數傳遞過去 this.$emit('row-click', row) } } } </script>
TableColumn.vue
<template> <el-table-column :label="columnHeader.label" :prop="columnHeader.label" align="center" > <!--columnHeader對應:column-header--> <template v-for="item in columnHeader.children"> <tableColumn v-if="item.children && item.children.length" :key="item.id" :column-header="item" /> <el-table-column v-else :key="item.name" :label="item.label" :prop="item.prop" align="center" /> </template> </el-table-column> </template> <script> export default { name: 'TableColumn', props: { columnHeader: { type: Object, required: true } } } </script> <style scoped> </style>
幾點重要說明:
(1)表格頭部的傳參主要分為兩類:帶children節點和不帶children節點的,如下圖所示
請註意children節點是為瞭完成復雜表頭的渲染,例如上面這個示例最終的表頭渲染樣式如下:
那麼問題來瞭,<el-table-column>是<el-table>的標簽,那這個<table-column>是個啥?
(2)DynamicTable.vue調用TableColumn.vue組件
DynamicTable.vue通過:column-header給TableColumn.vue傳遞帶children子節點的表頭信息,TableColumn.vue接收到這個節點信息後,主要做瞭以下兩件事情:
第一:通過<el-table-column>渲染瞭一個label標簽
第二:繼續判斷該節點是否存在children子節點
=> 如果存在children節點,繼續通過<table-column>進行渲染,繼續把這個子節點傳給TableColumn.vue組件,重復上述步驟
=> 如果不存在children節點,表示這是一個終止節點,通過<el-table-column>渲染結束
#2# -> 在展示頁面使用動態表格組件
<template> <div class="demo"> <el-card> <!--查詢區域--> <el-row :gutter="10"> <el-col :span="6"> <div class="grid-content bg-purple"> <span style="margin-right: 10px">選擇框 -</span> <el-select v-model="specified_table" placeholder="請選擇" > <el-option v-for="item in options" :key="item.zb_code" :label="item.zb_name" :value="item.zb_code" /> </el-select> </div> </el-col> <el-col :span="6"> <div class="grid-content bg-purple"> <el-button type="primary" plain @click="handleQueryClick">查 詢</el-button> </div> </el-col> </el-row> <!--表格區域--> <dynamic-table v-if="dynamicTableShow" :table-data="tableData" :table-header="tableHeaders" :height="'550px'" /> </el-card> </div> </template>
<script> // 引入組件 import DynamicTable from '@/components/Table/DynamicTable' // 獲取表頭信息 import { getTableHeader02_1, getTableHeader02_2, getTableHeader02_3, getTableHeader02_4 } from '@/api/table-header' export default { name: 'Index', components: { // 組件註冊 DynamicTable }, data () { return { // -- 查詢 ---------------------- options: [ // { zb_name: '指標名', zb_code: '指標代碼' } ], specified_table: '', // 指標值 // -- 表格 ---------------------- dynamicTableShow: true, // DynamicTable組件重新渲染變量 // 表頭數據 tableHeaders: [], // 表格數據 tableData: [] } }, created () { // api-獲取指標的下拉框數據 getSpecifiedTable().then(res => { this.options = res.data }) }, methods: { // 判斷值是否在數組中 isExistArr (arr, val) { return arr.includes(val) }, // 重新渲染表格 refreshTable (zb_code) { // 根據value值獲取label值 const obj = this.options.find((item) => { return item.zb_code === zb_code }) console.log(zb_code) console.log(obj.zb_name) // 設置dynamicTableShow為false,使得DynamicTable組件重新渲染 this.dynamicTableShow = false // 根據不同指標渲染不同的表頭 const TBArr01 = ['M01', 'M02', 'M03', 'M05'] // 第1類表 const TBArr02 = ['M04', 'M07', 'M08', 'M12'] // 第2類表 const TBArr03 = ['M09', 'M10', 'M11'] // 第3類表 const TBArr04 = ['M06'] // 第4類表 if (this.isExistArr(TBArr01, zb_code)) { this.tableHeaders = getTableHeader02_1(obj.zb_name) // 渲染表頭樣式1 } if (this.isExistArr(TBArr02, zb_code)) { this.tableHeaders = getTableHeader02_2(obj.zb_name) // 渲染表頭樣式2 } if (this.isExistArr(TBArr03, zb_code)) { this.tableHeaders = getTableHeader02_3(obj.zb_name) // 渲染表頭樣式3 } if (this.isExistArr(TBArr04, zb_code)) { this.tableHeaders = getTableHeader02_4(obj.zb_name) // 渲染表頭樣式4 } // api - 獲取表格數據 getTableList02(zb_code).then(res => { this.tableData = res.data }) // 此處是DOM還沒有更新,此處的代碼是必須的 this.$nextTick(() => { // DOM現在更新瞭 this.dynamicTableShow = true }) }, // 點擊[查詢]事件 handleQueryClick () { const zb_code = this.specified_table // 校驗查詢條件不能為空 if (zb_code === '' || zb_code === undefined) { this.$message.warning('指標不能為空!') } else { console.log('zb_code: ' + zb_code) // 重新渲染表頭和表格 this.refreshTable(zb_code) } } } } </script>
使用動態表格組件相對來說比較簡單,唯一需要註意的地方是,渲染表格頭部跟數據時必須需要添加以下代碼,不然頁面無法按照預期完成渲染。
this.$nextTick(() => { // DOM現在更新瞭 this.dynamicTableShow = true })
關於this.$nextTick()可以參考官網:https://cn.vuejs.org/v2/guide/reactivity.html
#3# -> 如何給動態表格根據需求動態添加序號列/索引列
在Element UI官方例子中,如果需要給table添加一個序號列或者索引列非常簡單,直接在<el-table>裡聲明一個特殊的<el-table-column>即可。
<el-table-column type="index" width="50"></el-table-column>
那如何在動態表格組件裡添加序號列呢?更甚者如果根據需要自行添加或者不添加?
首先我們來改造 DynamicTable.vue
像官方例子一樣,我們先在<el-table>裡也聲明一個<el-table-column>
<el-table-column v-if="isIndex" type="index" width="100" label="序號" align="center" />
註意到這裡有一個v-if綁定瞭一個isIndex值,這個值就是我們需要在父組件進行傳值的關鍵瞭
在props裡聲明isIndex為Boolean類型
props: { // 表格的數據 tableData: { type: Array, required: true }, // 多級表頭的數據 tableHeader: { type: Array, required: true }, // 表格的高度 height: { type: String, default: '300' }, // 是否需要添加序號列 isIndex: { type: Boolean } }
在展示頁面使用組件時通過:is-index傳入指定參數
<dynamic-table v-if="dynamicTableShow" :table-data="tableData" :table-header="tableHeaders" :height="'550px'" :is-index="true" />
在同頁面表頭需要切換的情況下,上面這種寫法容易在頁面初始化時候單獨顯示一個序號列,就像下面這樣,非常不美觀
我希望序號列可以和其他普通列一樣在表頭渲染的時候同時加載,可以這樣做
<dynamic-table v-if="dynamicTableShow" :table-data="tableData" :table-header="tableHeaders" :height="'550px'" :is-index="isAddIndex" />
將原本的常量“true”修改成一個變量isAddIndex替代,然後在表頭渲染完成的時候將其值修改成true
this.isAddIndex = true
這樣序號列就能跟其他普通列同時進行渲染瞭。
【參考資料】
https://www.jianshu.com/p/9c4ba833658f
https://www.cnblogs.com/llcdxh/p/9473458.html
到此這篇關於Element實現動態表格的示例代碼的文章就介紹到這瞭,更多相關Element 動態表格內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- element 表格多級表頭子列固定的實現
- element table 表格控件實現單選功能
- Element UI中table單元格合並的解決過程
- vue element 表頭添加斜線的實現代碼
- Element使用el-table組件二次封裝