index.vue
<template>
<el-table
v-if="show"
ref="txTable"
:data="data"
v-bind="$attrs"
@select="(selection, row) => $emit('select', selection, row)"
@select-all="selection => $emit('select-all', selection)"
@selection-change="selection => $emit('selection-change', selection)"
@cell-click="(row, column, cell, event) => $emit('cell-click', row, column, cell, event)"
@cell-dblclick="(row, column, cell, event) => $emit('cell-dblclick', row, column, cell, event)"
@row-click="(row, column, event) => $emit('row-click', row, column, event)">
<slot name="header" />
<template v-for="(item, index) of columns">
<template v-if="item.show">
<el-table-column v-if="item.children && item.children.length" :key="index" v-bind="item.attr">
<TxTableColumn v-for="(subItem, subIndex) of item.children" :key="subIndex + '0' + index" :item="subItem" />
</el-table-column>
<TxTableColumn v-else :key="index" :item="item.attr" />
</template>
</template>
<slot />
</el-table>
</template>
<script>
import TxTableColumn from './txTableColumn'
export default {
name: 'TxTable',
components: { TxTableColumn },
props: {
data: { type: Array, default: () => [] },
columns: { type: Array, default: () => [] },
},
data() {
return { show: true }
},
}
</script>
- 通过 v-bind="$attrs" 绑定 props 传递过来的所有属性
- 通过 $emit 将时间绑定到附件上,实现跟 element-ui table 一样的事件监听
- 这里只考虑 二级表头
- 通过 v-if="show" 来重新渲染表格,避免更多筛选后,table 错位问题
txTableColumn.vue
<template>
<el-table-column v-if="item.render" v-bind="item">
<template slot-scope="scope">
<TxTableSolt :render="item.render" :row="scope.row" :index="scope.$index" :column="item" />
</template>
</el-table-column>
<el-table-column v-else v-bind="item" />
</template>
<script>
import TxTableSolt from './txTableSolt'
export default {
components: { TxTableSolt },
props: {
item: { type: Object, required: true },
},
}
</script>
- 这里自定义 TxTableSolt 实现 定义 render 函数
txTableMore.vue
<template>
<div class="tx-table-more clearfix">
<span>{{ label }}</span>
<el-popover
v-model="isPannel"
placement="bottom-end"
title="请选择展示的字段"
:width="width"
trigger="click"
popper-class="tx-table-pannel">
<i slot="reference" :class="icon" class="more-filter" />
<div class="oper-pannel">
<el-checkbox v-model="checkAll" label="全选" :indeterminate="isIndeterminate" @change="allChange" />
<ul>
<li v-for="(item, index) of list" :key="index">
<el-checkbox v-model="item.show" :label="item.attr.label" @change="itemChange" />
</li>
</ul>
<div class="btn-wrap">
<el-button @click="isPannel = false">取消</el-button>
<el-button type="primary" @click="confirm">确定</el-button>
</div>
</div>
</el-popover>
</div>
</template>
<script>
import { cloneDeep } from 'lodash'
export default {
props: {
label: { type: String, default: '' },
icon: { type: String, default: 'el-icon-more' },
width: { type: Number, default: 200 },
columns: { type: Array, required: true },
},
data() {
return {
list: [],
isPannel: false,
isIndeterminate: false,
checkAll: true,
}
},
created() {
this.list = cloneDeep(this.columns.filter(e => e.more === true))
this.itemChange()
},
methods: {
allChange(val) {
this.checkAll = val
this.isIndeterminate = false
this.list.forEach(e => (e.show = val))
},
itemChange() {
this.isIndeterminate = this.list.some(e => e.show === true)
!this.isIndeterminate && (this.checkAll = false)
if (this.list.every(e => e.show === true)) {
this.checkAll = true
this.isIndeterminate = false
}
},
confirm() {
this.list.forEach(e => {
const item = this.columns.find(se => se.attr.label === e.attr.label)
item.show = e.show
})
this.$parent.$parent.$parent.show = false
this.$nextTick(() => {
this.$parent.$parent.$parent.show = true
this.isPannel = false
})
},
},
}
</script>
<style lang="scss" scoped>
.tx-table-more {
position: relative;
.more-filter {
float: right;
margin-top: 4px;
transform: rotate(90deg);
font-size: 14px;
cursor: pointer;
&:hover {
color: $themeColor;
}
}
}
</style>
txTableSolt.vue
<script>
export default {
functional: true,
props: {
row: { type: Object, required: true },
render: { type: Function, required: true },
index: { type: Number, required: true },
column: { type: Object, default: null },
},
render: (h, data) => {
const props = data.props
const params = {
row: props.row,
index: props.index,
}
if (props.column) params.column = props.column
return props.render(params, h)
},
}
</script>
tx-table 正确使用姿势
<template>
<TxTable
ref="queryTable"
:data="tableData"
:columns="columns"
:height="800"
@selection-change="val => (sectionList = val)">
<template slot="header" />
<el-table-column min-width="90" align="center" fixed="right">
<template slot="header">
<TxTableMore :columns="columns" label="操作" />
</template>
<template slot-scope="scope">
<el-button type="text">确认</el-button>
<el-button type="text">编辑</el-button>
<el-button type="text">删除</el-button>
</template>
</el-table-column>
</TxTable>
</template>
<script>
import TxTable from '@/components/table'
import TxTableMore from '@/components/table/txTableMore'
import columns from './components/columns'
export default {
components: { TxTableMore, TxTable },
data() {
return {
tableData: [],
sectionList: [],
columns: columns(this),
}
},
}
</script>
import { currency, date, number, multiply } from '@/utils/filters'
import columnStatus from '../components/Status'
function columns(that) {
return [
{ show: true, attr: { type: 'selection', width: 45, align: 'center', fixed: 'left' } },
{ show: true, attr: { type: 'index', label: '序号', width: 45, align: 'center', fixed: 'left' } },
{ more: true, show: true, attr: { label: '业务类型' }, 'min-width': 90, prop: 'bussTypeCode' },
{
more: true,
show: true,
attr: {
label: '机构',
'min-width': 200,
render: ({ row }, h) => {
if (that.auth.key) {
return (
<span class='table-link' onClick={() => that.levelHandler('机构', row)}>
{row.orgCode} {row.orgName}
</span>
)
} else {
return (
<span>
{row.orgCode} {row.orgName}
</span>
)
}
},
},
},
{
more: true,
show: true,
attr: { label: '环比校验', align: 'center' },
children: [
{
label: '数据',
'min-width': 120,
render: ({ row }, h) => {
return <span>{number(row.hgjyValue)}</span>
},
},
{
label: '比列',
'min-width': 80,
render: ({ row }, h) => {
return <span>{multiply(row.hbjyPercent)}</span>
},
},
],
},
]
}
export default columns