这个表格写了很久了,最近才整理。
自定义表格可以根据数据自动生成表头,多级表头,列
约定的数据格式如下:
/** 数据格式
*
headList:[
{
prop:"date",
label:"日期",
width:"150",
url:'',
path:'',
yl:'',
children:[]
},
{
prop:"",
label:"地址",
width:"",
url:'',
path:'',
yl:'',
children:[{
prop:"province",
label:"省份",
width:"120",
url:'',
path:'',
yl:'',
},
{
prop:"zip",
label:"邮编",
width:"120",
url:'',
path:'',
yl:'',
}
]
}
],
tableData: [{
date: '2016-05-03',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333
}]
*
*/
HeadTable.vue
<template>
<el-table
v-loading.iTable="loading"
:data="tableDatas"
:row-style="selectedRowStyle"
:row-class-name="rowStyle"
style="width: 100%"
:height="height"
stripe
border
@row-click="scaleRow"
@row-dblclick="dblclick"
@sort-change="sortchange"
>
<!--:span-method="objectSpanMethod"-->
<template>
<el-table-column
v-for="(column,index) in headList"
:key="index"
:label="column.label"
align="center"
:fixed="column.gd && column.gd.indexOf(column.prop)>-1 "
:width="column.width"
show-overflow-tooltip
:prop="column.prop"
:sortable="(!(column.children && column.children.length !== 0 || column.label === '序号' || column.label === '操作' || column.label === '得分组成'))?'custom':false"
>
<template v-if="column.children && column.children.length !== 0">
<el-table-column
v-for="(column1,index1) in column.children"
:key="index1"
align="center"
:label="column1.label"
:width="column1.width"
show-overflow-tooltip
:prop="column1.prop"
sortable="custom"
>
<template slot-scope="scope">
<div v-if="(column1.hasOwnProperty('path')&&column1.path&&column1.path.length!==0)||(column1.hasOwnProperty('url')&&column1.url&&column1.url.length!==0)">
<el-button
style="border: none;padding: 0;"
:style="[{color:column1.higlight!=='#464646'?column1.higlight:''}]"
class="cell_span"
:class="clickedRow==scope.row.index?'scale-row':''"
@click="toputh(column1,scope.row)"
>{{ scope.row[(column1.prop+(column1.yl?column1.yl:''))] }}</el-button>
</div>
<div v-else>
<span :style="[{color:column1.higlight}]">{{ scope.row[(column1.prop+(column1.yl?column1.yl:''))] }}</span>
</div>
</template>
</el-table-column>
</template>
<template slot-scope="scope">
<div v-if="(column.hasOwnProperty('path')&&column.path&&column.path.length!==0)||(column.hasOwnProperty('url')&&column.url&&column.url.length!==0)">
<el-button
style="border: none;padding: 0;"
:style="[{color:column.higlight!=='#464646'?column.higlight:''}]"
class="cell_span"
:class="clickedRow==scope.row.index?'scale-row':''"
@click="toputh(column,scope.row)"
>{{ scope.row[(column.prop+(column.yl?column.yl:''))] }}</el-button>
</div>
<div v-else>
<span :style="[{color:column.higlight}]">{{ scope.row[(column.prop+(column.yl?column.yl:''))] }}</span>
</div>
</template>
</el-table-column>
</template>>
</el-table>
</template>
<script>
/**
* @author wangligang
* @date 2020/8/4
* @Description:
* @update by: 表格组件
*
*
/
const evalData = (data) => {
const tmp = []
Array.from(data).forEach((row, index) => {
if (!Array.isArray(row)) {
tmp.push({ no: index + 1, ...row })
} else {
//
}
})
return tmp
}
export default {
props: {
tableData: {
type: [Array, Object],
required: true
},
headList: {
type: Array,
default: () => []
},
query: {
type: Object,
default: () => {}
},
height: {
type: String,
default: () => 'calc(100vh - 220px)'
},
loading: {
type: Boolean,
default: () => false
}
},
data() {
return {
clickedRow: -1,
spanArr: [],
pos: 0
}
},
computed: {
// 格式化表格数据
tableDatas: function() {
const tmp = !Array.isArray(this.tableData) ? [this.tableData] : this.tableData
this.getSpanArr(evalData(tmp))
return evalData(tmp)
}
},
methods: {
getSpanArr(data) {
this.spanArr = []
this.pos = 0
for (var i = 0; i < data.length; i++) {
if (i === 0) {
this.spanArr.push(1)
this.pos = 0
} else {
// 判断当前元素与上一个元素是否相同
if (data[i].nsrsbh && data[i].nsrsbh === data[i - 1].nsrsbh) {
this.spanArr[this.pos] += 1
this.spanArr.push(0)
} else {
this.spanArr.push(1)
this.pos = i
}
}
}
},
dblclick(row, column, event) {
let data = {}
let Y = false
this.headList.map(item => {
if (item.label === '操作') {
data = item
Y = true
} else if (item.url && item.url.length !== 0) {
Y = true
}
})
if (Y) {
this.$emit('dblclick', row, data)
}
},
toputh(row, data) {
if (row.path && row.path.length !== 0) {
this.$router.push({ path: row.path, query: { ...this.query }})
} else if (row.url && row.url.length !== 0) {
this.$emit('urlClick', row, data)
}
},
scaleRow(row) {
this.clickedRow = row.index
},
rowStyle({ rowIndex }) {
if (this.clickedRow === rowIndex) {
return 'scale-row'
}
},
selectedRowStyle({ row, rowIndex }) {
row.index = rowIndex
},
sortchange({ column, prop, order }) {
this.$emit('sortchange', { column, prop, order })
},
objectSpanMethod({ row, column, rowIndex, columnIndex }) {
if (!row.nsrsbh) {
this.obj = { row, column, rowIndex, columnIndex }
return {
rowspan: 1,
colspan: 1
}
}
if (row.columnspan.indexOf(column.property) > -1) {
const _row = this.spanArr[rowIndex]
const _col = _row > 0 ? 1 : 0
return {
rowspan: _row,
colspan: _col
}
}
}
}
}
</script>
<style lang="scss">
.el-table{
.scale-row{
font-size:15px;
font-weight:600;
background-color:#f5f7fa;
transition:all .3s ease-in-out;
}
.bg-disable{
background:rgba(224,224,224,.3);
}
.bg-active{
background: #bccbe4;
}
}
</style>
使用方式
引入组件
<HeadTable :headList="headList" :tableData="tableData"></HeadTable>