vue+ElementUI更像Excel的表格組件使用詳解
一、表格效果

二、核心思想
不做前端的人,會(huì)覺(jué)得“一”中圖展示的就是一張表格;做前端的,看完“四”中注釋的業(yè)務(wù)邏輯(可能看不懂,但無(wú)所謂,業(yè)務(wù)邏輯嘛,重要的是處理思想),會(huì)更覺(jué)得像Excel,自然也就不能直接將“三”中數(shù)據(jù)賦給el-table。
處理的核心思想就是先處理出表頭(列prop賦值為順序排列的小寫(xiě)字母)、第一列,再根據(jù)每一列的表頭和第一行的數(shù)據(jù)找出填充的值(有點(diǎn)像直接坐標(biāo)系,表頭為X軸,第一列為Y軸)。
三、數(shù)據(jù)格式

四、組件代碼
<template>
<div>
<div v-for="(table, index) in tables" :key="'table'+index" class="tables">
<el-tag size="medium" effect="dark">{{ table.name }}</el-tag>
<el-table :data="table.dataSource" border>
<el-table-column v-for="column in table.columns" :key="'table'+index+column.prop" :prop="column.prop" :label="column.label" :min-width="column.minWidth" :align="column.align" :show-overflow-tooltip="column.tooltip"></el-table-column>
</el-table>
</div>
</div>
</template>
<script>
export default {
props: {
params: {
type: Object,
default () {
return {
tempCheck: [],
temperatureCompensation: [],
linear: [],
linearCheck: []
}
}
}
},
computed: {
tables () {
let tables = [
{
//表格名稱
name: '溫補(bǔ)結(jié)果',
//表格列,數(shù)據(jù)未處理之前寫(xiě)死在columns中的是固定列,其余列根據(jù)需求及數(shù)據(jù)處理而來(lái)
columns: [ //其余列是數(shù)據(jù)里不重復(fù)的pressPoint字段值+單位kPa
{
prop: 'a',
label: '溫度℃', //列數(shù)據(jù)為不重復(fù)的temperaturePoint值
minWidth: 100,
align: 'center'
},
{
prop: 'b',
label: '溫度AD', //只和溫度temperaturePoint有關(guān),列數(shù)據(jù)為不同temperaturePoint對(duì)應(yīng)的temperatureAD值
minWidth: 100,
align: 'center'
}
],
//表格數(shù)據(jù),展示temperaturePoint和pressPoint對(duì)應(yīng)的pressAD,數(shù)據(jù)來(lái)源params.temperatureCompensation
dataSource: []
},
{
name: '線性化結(jié)果',
columns: [], //不重復(fù)的pressPoint字段值+單位kPa
dataSource: [{}] //只會(huì)有一行數(shù)據(jù),展示pressPoint對(duì)應(yīng)的pressAD, 數(shù)據(jù)來(lái)源params.linear
},
{
name: '溫補(bǔ)校驗(yàn)結(jié)果',
columns: [ //其余列是數(shù)據(jù)里不重復(fù)的temperaturePoint+單位℃
{
prop: 'a',
label: '壓力', //列數(shù)據(jù)為不重復(fù)的pressPoint
minWidth: 100,
align: 'center'
}
],
dataSource: [] //展示temperaturePoint和pressPoint對(duì)應(yīng)的press,數(shù)據(jù)來(lái)源params.tempCheck
},
{
name: '線性化校驗(yàn)結(jié)果',
columns: [], //不重復(fù)的pressPoint字段值+單位kPa
dataSource: [{}] //只會(huì)有一行數(shù)據(jù),展示pressPoint對(duì)應(yīng)的press,數(shù)據(jù)來(lái)源params.linearCheck
}
],
//根據(jù)tables注釋的業(yè)務(wù)邏輯開(kāi)始處理數(shù)據(jù)
columns = this.getXYNoRepeatData('temperatureCompensation', 'pressPoint').map((li, index) => {
return {
prop: String.fromCharCode(99+index),
label: li+'kPa',
minWidth: 100,
align: 'center'
}
}), dataSource = this.getXYNoRepeatData('temperatureCompensation', 'temperaturePoint').map(li => {
return {
a: li,
b: this.getADColumn('temperatureCompensation', li, 'temperaturePoint', 'temperatureAD')
};
}), errorRateList = [], errorRate = '', errorRateRrop = '';
columns.forEach(column => {
dataSource.forEach(d => {
Object.assign(d, {
[column.prop]: this.getValueByXY('temperatureCompensation', column.label.replace('kPa', ''), d.a, 'pressPoint', 'temperaturePoint', 'pressAD')
});
});
});
tables[0].columns = tables[0].columns.concat(columns);
tables[0].dataSource = dataSource; //完成溫補(bǔ)結(jié)果columns、dataSource計(jì)算
//計(jì)算線性化結(jié)果columns、dataSource
columns = this.getXYNoRepeatData('linear', 'pressPoint').map((li, index) => {
return {
prop: String.fromCharCode(97+index), //列prop處理為順序排列的小寫(xiě)英文字母
label: li+'kPa',
minWidth: 100,
align: 'center'
}
});
tables[1].columns = columns;
columns.forEach(column => {
Object.assign(tables[1].dataSource[0], {
[column.prop]: this.getValueByX('linear', column.label.replace('kPa', ''), 'pressPoint', 'pressAD')
});
});
//計(jì)算溫補(bǔ)校驗(yàn)結(jié)果columns、dataSource
columns = this.getXYNoRepeatData('tempCheck', 'temperaturePoint').map((li, index) => {
return {
prop: String.fromCharCode(98+index),
label: li+'℃',
minWidth: 100,
align: 'center'
}
});
dataSource = this.getXYNoRepeatData('tempCheck', 'pressPoint').map(li => {
return {
a: li+'kPa'
};
});
columns.forEach(column => {
dataSource.forEach(d => {
Object.assign(d, {
[column.prop]: this.getValueByXY('tempCheck', column.label.replace('℃', ''), d.a.replace('kPa', ''), 'temperaturePoint', 'pressPoint', 'press')
});
});
});
errorRateRrop = String.fromCharCode(98+columns.length);
columns.push({ //固定最后一列
prop: errorRateRrop,
label: '最大誤差%', //列數(shù)據(jù)為每行temperaturePoint、pressPoint對(duì)應(yīng)的errorRate的最大值
minWidth: 100,
align: 'center'
});
dataSource.forEach(d => {
errorRateList = [];
for(let i=0; i<columns.length-1; i++) {
errorRate = this.getValueByXY('tempCheck', columns[i].label.replace('℃', ''), d.a.replace('kPa', ''), 'temperaturePoint', 'pressPoint', 'errorRate');
errorRate===''?'':errorRateList.push(errorRate);
}
if(errorRateList.length>0) {
errorRateList.sort((a, b) => {
return b-a;
});
Object.assign(d, {
[errorRateRrop]: errorRateList[0]
});
} else {
Object.assign(d, {
[errorRateRrop]: ''
});
}
});
tables[2].columns = tables[2].columns.concat(columns);
tables[2].dataSource = dataSource;
//計(jì)算線性化校驗(yàn)結(jié)果columns、dataSource
columns = this.getXYNoRepeatData('linearCheck', 'pressPoint').map((li, index) => {
return {
prop: String.fromCharCode(97+index),
label: li+'kPa',
minWidth: 100,
align: 'center'
}
});
columns.forEach(column => {
Object.assign(tables[3].dataSource[0], {
[column.prop]: this.getValueByX('linearCheck', column.label.replace('kPa', ''), 'pressPoint', 'press')
});
});
errorRateRrop = String.fromCharCode(97+columns.length);
columns.push({
prop: errorRateRrop,
label: '最大誤差%',
minWidth: 100,
align: 'center'
});
errorRateList = this.params.result.linearCheck.map(li => {
return li.errorRate;
}).sort((a, b) => {
return b-a;
});
Object.assign(tables[3].dataSource[0], {
[errorRateRrop]: errorRateList.length>0?errorRateList[0]:''
});
tables[3].columns = columns;
return tables;
}
},
methods: {
getXYNoRepeatData (vari, variable) {
let arr = this.params[vari].map(li => {
return li[variable];
}).sort((a, b) => {
return a-b;
}), set = new Set(arr);
return Array.from(set.values());
},
getADColumn (vari, val, valueField, labelField) {
let item = this.params[vari].find(li => li[valueField]===val);
return item?item[labelField].toFixed(1):'';
},
getValueByXY (vari, x, y, xField, yField, valueField) {
let item = this.params[vari].find(li => li[xField]==x&&li[yField]==y);
return item?item[valueField].toFixed(valueField.includes('AD')?1:3):'';
},
getValueByX (vari, x, xField, valueField) {
let item = this.params[vari].find(li => li[xField]==x);
return item?item[valueField].toFixed(valueField.includes('AD')?1:3):'';
}
}
}
</script>
<style scoped>
.tables >>>.el-tag {
margin: 20px 0 10px 0;
}
</style>總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
vue如何設(shè)置描點(diǎn)跳轉(zhuǎn)到對(duì)應(yīng)頁(yè)面
這篇文章主要介紹了vue如何設(shè)置描點(diǎn)跳轉(zhuǎn)到對(duì)應(yīng)頁(yè)面問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-05-05
vue cli使用融云實(shí)現(xiàn)聊天功能的實(shí)例代碼
最近小編接了一個(gè)新項(xiàng)目,項(xiàng)目需求要實(shí)現(xiàn)一個(gè)聊天功能,今天小編通過(guò)實(shí)例代碼給大家介紹vue cli使用融云實(shí)現(xiàn)聊天功能的方法,感興趣的朋友跟隨小編一起看看吧2019-04-04
Vue如何根據(jù)角色獲取菜單動(dòng)態(tài)添加路由
這篇文章主要介紹了Vue如何根據(jù)角色獲取菜單動(dòng)態(tài)添加路由,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2024-01-01
利用Vue實(shí)現(xiàn)將圖片轉(zhuǎn)換為Base64編碼的方法
這篇文章主要介紹了利用Vue實(shí)現(xiàn)將圖片轉(zhuǎn)換為Base64編碼的方法,Base64是一種編碼方式,用于將二進(jìn)制數(shù)據(jù)轉(zhuǎn)換成64個(gè)基于ASCII的可打印字符,這種編碼可嵌入圖像到HTML或CSS中,減少加載時(shí)間,解決跨域問(wèn)題,并支持離線應(yīng)用開(kāi)發(fā),需要的朋友可以參考下2024-10-10
vue實(shí)現(xiàn)標(biāo)簽頁(yè)切換/制作tab組件詳細(xì)教程
在項(xiàng)目開(kāi)發(fā)中需要使用vue實(shí)現(xiàn)tab頁(yè)簽切換功能,所以這里總結(jié)下,這篇文章主要給大家介紹了關(guān)于vue實(shí)現(xiàn)標(biāo)簽頁(yè)切換/制作tab組件的相關(guān)資料,需要的朋友可以參考下2023-11-11
Vue.js 實(shí)現(xiàn)tab切換并變色操作講解
這篇文章主要介紹了Vue.js 實(shí)現(xiàn)tab切換并變色操作講解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-09-09
vue-cli腳手架搭建的項(xiàng)目去除eslint驗(yàn)證的方法
今天小編就為大家分享一篇vue-cli腳手架搭建的項(xiàng)目去除eslint驗(yàn)證的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-09-09
Vue+Element-UI實(shí)現(xiàn)上傳圖片并壓縮
這篇文章主要為大家詳細(xì)介紹了Vue+Element-UI實(shí)現(xiàn)上傳圖片并壓縮功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-11-11

