Element實(shí)現(xiàn)動(dòng)態(tài)表格的示例代碼
【代碼背景】
有這樣一個(gè)業(yè)務(wù)需求場(chǎng)景,有大概十幾張表歸屬于某個(gè)類(lèi)別,用戶希望在同一個(gè)頁(yè)面,通過(guò)選擇不同的查詢指標(biāo)展示不同的表格,這些表的表頭樣式類(lèi)似但是又不完全相同,怎么做呢?
到目前為止所有基于Element UI的表格樣式都是直接在頁(yè)面寫(xiě)死的,像官方這樣:
<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>
要解決上述問(wèn)題,最簡(jiǎn)單暴力的方式是為每個(gè)表寫(xiě)一個(gè)單獨(dú)組件,然后通過(guò)select框觸發(fā)事件切換不同組件路由渲染頁(yè)面,當(dāng)然這種方式很笨,也不符合代碼復(fù)用的基本原則,所以為了偷懶,為了堅(jiān)守代碼復(fù)用的基本原則,開(kāi)始思考有沒(méi)有更好的方式來(lái)解決這個(gè)問(wèn)題。
仔細(xì)觀察這個(gè)<el-table>,表格數(shù)據(jù)是通過(guò):data綁定的,表格頭部數(shù)據(jù)則是通過(guò)<el-table-column>標(biāo)簽展示的,表頭數(shù)據(jù)是不是也可以通過(guò)某種傳參的方式結(jié)合v-for來(lái)渲染<el-table-column>的具體數(shù)據(jù)呢?在度娘的幫助下,果然有大佬已經(jīng)這樣做了,實(shí)現(xiàn)了動(dòng)態(tài)表格,參考鏈接掛在最底下了哦,在此特別感謝免費(fèi)分享知識(shí)的大佬們,知識(shí)無(wú)價(jià),學(xué)無(wú)止境。
現(xiàn)將本項(xiàng)目的具體實(shí)現(xiàn)代碼記錄如下,完善了一些代碼的注解,嘗試幫助理解。
【代碼實(shí)現(xiàn)】
#1# -> 代碼復(fù)用的基礎(chǔ)是你需要一個(gè)可復(fù)用的組件
在/components/Table文件夾下新建兩個(gè)組件
DynamicTable.vue
<template> <!-- 動(dòng)態(tài)展示表格 --> <el-table :data="tableData" border stripe :height="height" @row-click="handleRowClick"> <!-- v-for 循環(huán)取表頭數(shù)據(jù) --> <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: { // 表格的數(shù)據(jù) tableData: { type: Array, required: true }, // 多級(jí)表頭的數(shù)據(jù) tableHeader: { type: Array, required: true }, // 表格的高度 height: { type: String, default: '300' } }, methods: { // 行點(diǎn)擊事件 handleRowClick (row, column, event) { // console.log(row) // console.log(column) // console.log(event) // 通知調(diào)用父組件的row-click事件 // row作為參數(shù)傳遞過(guò)去 this.$emit('row-click', row) } } } </script>
TableColumn.vue
<template> <el-table-column :label="columnHeader.label" :prop="columnHeader.label" align="center" > <!--columnHeader對(duì)應(yīng):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>
幾點(diǎn)重要說(shuō)明:
(1)表格頭部的傳參主要分為兩類(lèi):帶children節(jié)點(diǎn)和不帶children節(jié)點(diǎn)的,如下圖所示
請(qǐng)注意children節(jié)點(diǎn)是為了完成復(fù)雜表頭的渲染,例如上面這個(gè)示例最終的表頭渲染樣式如下:
那么問(wèn)題來(lái)了,<el-table-column>是<el-table>的標(biāo)簽,那這個(gè)<table-column>是個(gè)啥?
(2)DynamicTable.vue調(diào)用TableColumn.vue組件
DynamicTable.vue通過(guò):column-header給TableColumn.vue傳遞帶children子節(jié)點(diǎn)的表頭信息,TableColumn.vue接收到這個(gè)節(jié)點(diǎn)信息后,主要做了以下兩件事情:
第一:通過(guò)<el-table-column>渲染了一個(gè)label標(biāo)簽
第二:繼續(xù)判斷該節(jié)點(diǎn)是否存在children子節(jié)點(diǎn)
=> 如果存在children節(jié)點(diǎn),繼續(xù)通過(guò)<table-column>進(jìn)行渲染,繼續(xù)把這個(gè)子節(jié)點(diǎn)傳給TableColumn.vue組件,重復(fù)上述步驟
=> 如果不存在children節(jié)點(diǎn),表示這是一個(gè)終止節(jié)點(diǎn),通過(guò)<el-table-column>渲染結(jié)束
#2# -> 在展示頁(yè)面使用動(dòng)態(tài)表格組件
<template> <div class="demo"> <el-card> <!--查詢區(qū)域--> <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="請(qǐng)選擇" > <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> <!--表格區(qū)域--> <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: { // 組件注冊(cè) DynamicTable }, data () { return { // -- 查詢 ---------------------- options: [ // { zb_name: '指標(biāo)名', zb_code: '指標(biāo)代碼' } ], specified_table: '', // 指標(biāo)值 // -- 表格 ---------------------- dynamicTableShow: true, // DynamicTable組件重新渲染變量 // 表頭數(shù)據(jù) tableHeaders: [], // 表格數(shù)據(jù) tableData: [] } }, created () { // api-獲取指標(biāo)的下拉框數(shù)據(jù) getSpecifiedTable().then(res => { this.options = res.data }) }, methods: { // 判斷值是否在數(shù)組中 isExistArr (arr, val) { return arr.includes(val) }, // 重新渲染表格 refreshTable (zb_code) { // 根據(jù)value值獲取label值 const obj = this.options.find((item) => { return item.zb_code === zb_code }) console.log(zb_code) console.log(obj.zb_name) // 設(shè)置dynamicTableShow為false,使得DynamicTable組件重新渲染 this.dynamicTableShow = false // 根據(jù)不同指標(biāo)渲染不同的表頭 const TBArr01 = ['M01', 'M02', 'M03', 'M05'] // 第1類(lèi)表 const TBArr02 = ['M04', 'M07', 'M08', 'M12'] // 第2類(lèi)表 const TBArr03 = ['M09', 'M10', 'M11'] // 第3類(lèi)表 const TBArr04 = ['M06'] // 第4類(lèi)表 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 - 獲取表格數(shù)據(jù) getTableList02(zb_code).then(res => { this.tableData = res.data }) // 此處是DOM還沒(méi)有更新,此處的代碼是必須的 this.$nextTick(() => { // DOM現(xiàn)在更新了 this.dynamicTableShow = true }) }, // 點(diǎn)擊[查詢]事件 handleQueryClick () { const zb_code = this.specified_table // 校驗(yàn)查詢條件不能為空 if (zb_code === '' || zb_code === undefined) { this.$message.warning('指標(biāo)不能為空!') } else { console.log('zb_code: ' + zb_code) // 重新渲染表頭和表格 this.refreshTable(zb_code) } } } } </script>
使用動(dòng)態(tài)表格組件相對(duì)來(lái)說(shuō)比較簡(jiǎn)單,唯一需要注意的地方是,渲染表格頭部跟數(shù)據(jù)時(shí)必須需要添加以下代碼,不然頁(yè)面無(wú)法按照預(yù)期完成渲染。
this.$nextTick(() => { // DOM現(xiàn)在更新了 this.dynamicTableShow = true })
關(guān)于this.$nextTick()可以參考官網(wǎng):https://cn.vuejs.org/v2/guide/reactivity.html
#3# -> 如何給動(dòng)態(tài)表格根據(jù)需求動(dòng)態(tài)添加序號(hào)列/索引列
在Element UI官方例子中,如果需要給table添加一個(gè)序號(hào)列或者索引列非常簡(jiǎn)單,直接在<el-table>里聲明一個(gè)特殊的<el-table-column>即可。
<el-table-column type="index" width="50"></el-table-column>
那如何在動(dòng)態(tài)表格組件里添加序號(hào)列呢?更甚者如果根據(jù)需要自行添加或者不添加?
首先我們來(lái)改造 DynamicTable.vue
像官方例子一樣,我們先在<el-table>里也聲明一個(gè)<el-table-column>
<el-table-column v-if="isIndex" type="index" width="100" label="序號(hào)" align="center" />
注意到這里有一個(gè)v-if綁定了一個(gè)isIndex值,這個(gè)值就是我們需要在父組件進(jìn)行傳值的關(guān)鍵了
在props里聲明isIndex為Boolean類(lèi)型
props: { // 表格的數(shù)據(jù) tableData: { type: Array, required: true }, // 多級(jí)表頭的數(shù)據(jù) tableHeader: { type: Array, required: true }, // 表格的高度 height: { type: String, default: '300' }, // 是否需要添加序號(hào)列 isIndex: { type: Boolean } }
在展示頁(yè)面使用組件時(shí)通過(guò):is-index傳入指定參數(shù)
<dynamic-table v-if="dynamicTableShow" :table-data="tableData" :table-header="tableHeaders" :height="'550px'" :is-index="true" />
在同頁(yè)面表頭需要切換的情況下,上面這種寫(xiě)法容易在頁(yè)面初始化時(shí)候單獨(dú)顯示一個(gè)序號(hào)列,就像下面這樣,非常不美觀
我希望序號(hào)列可以和其他普通列一樣在表頭渲染的時(shí)候同時(shí)加載,可以這樣做
<dynamic-table v-if="dynamicTableShow" :table-data="tableData" :table-header="tableHeaders" :height="'550px'" :is-index="isAddIndex" />
將原本的常量“true”修改成一個(gè)變量isAddIndex替代,然后在表頭渲染完成的時(shí)候?qū)⑵渲敌薷某蓆rue
this.isAddIndex = true
這樣序號(hào)列就能跟其他普通列同時(shí)進(jìn)行渲染了。
【參考資料】
https://www.jianshu.com/p/9c4ba833658f
https://www.cnblogs.com/llcdxh/p/9473458.html
到此這篇關(guān)于Element實(shí)現(xiàn)動(dòng)態(tài)表格的示例代碼的文章就介紹到這了,更多相關(guān)Element 動(dòng)態(tài)表格內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue組件高級(jí)通訊之$attrs與$listeners
這篇文章主要為大家介紹了Vue組件高級(jí)通訊之$attrs與$listeners使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-06-06Vue不能watch數(shù)組和對(duì)象變化解決方案
這篇文章主要為大家介紹了Vue不能watch數(shù)組和對(duì)象變化解決方案示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11vue?axios?form-data格式傳輸數(shù)據(jù)和文件方式
這篇文章主要介紹了vue?axios?form-data格式傳輸數(shù)據(jù)和文件方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-05-05Vue Object 的變化偵測(cè)實(shí)現(xiàn)代碼
這篇文章主要介紹了Vue Object的變化偵測(cè)實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04vue環(huán)形進(jìn)度條組件實(shí)例應(yīng)用
在本文中我們給大家分享了關(guān)于vue環(huán)形進(jìn)度條組件的使用方法以及實(shí)例代碼,需要的朋友們跟著測(cè)試下吧。2018-10-10element vue Array數(shù)組和Map對(duì)象的添加與刪除操作
這篇文章主要介紹了element vue Array數(shù)組和Map對(duì)象的添加與刪除功能,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-11-11