一、el-table测试数据生成
自定义结构 测试数据生成---适配结构:
{ columnType: 'common', label: '交易所', prop: 'exchange', align: 'left', minWidth: 80, fixed: false },
const columns = [
{ dataType: '', tradeType: '', label: '交易所', prop: 'exchange', align: 'left', minWidth: 80, fixed: false },
{ dataType: '', tradeType: '', label: '产品', prop: 'product', align: 'left', minWidth: 80, fixed: false },
{ dataType: '', tradeType: '', label: '月份', prop: 'month', align: 'left', minWidth: 80, fixed: false }
]
// 按结构字段设置测试数据(columns为字段结构,count为返回数据列表数)
function getTestData(columns, count){
// 提供dataType进行数据类型判断
let data = []
function getTestData (columns, count) {
// 提供dataType进行数据类型判断
let data = []
for (let i = 0; i < count; i++) {
let obj = {}
columns.forEach(o => {
for (let pro in o) {
if (pro === 'prop')
obj[o[pro]] = String(Math.floor(Math.random() * 10000000))
}
})
data.push(obj)
}
console.log(data)
return data
}
适用于样式判别、Formatter
<el-table-column
v-for="(item, index) in tableStruct"
:key="index"
:label="item.label"
:prop="item.prop"
:min-width="item.width"
:align="item.align"
:show-overflow-tooltip="item.showOverFlow"
>
<template slot-scope="props">
<div
:class="{
'cell-value-can-click': props.row[item.prop + 'CanClick']
}"
:style="{ fontWeight: props.row[item.prop + 'Bold'] ? 600 : 500 }"
@click="
props.row[item.prop + 'CanClick'] && cellClick(props.row, item)
"
>
<div v-if="props.row[item.prop + 'NumberType'] === 'number2'">
{{ amtFormatter(props.row[item.prop], 2) }}
</div>
</div>
</template>
</el-table-column>
二、el-table组织树形数据
3.1.分组组织数据(列表数据到树形数据)
[[DCE, eb], [DCE, eb]]===》
[ { "exchange": "DCE", "product": [ "eb", "i" ]
}
]
[{"product": "eb", "exchange": "DCE"},{"product": "i","exchange": "DCE"},]===>
[{exchange: 'DCE', product: [{"product": "eb", "exchange": "DCE"}, {"product": "eb", "exchange": "DCE"}]},
{exchange: 'DCE', product: [{"product": "eb", "exchange": "DCE"}, {"product": "eb", "exchange": "DCE"}]},]
操作方法:
/**
* 数据处理(首页 selectMmProductByDate 交易所-品种)---两级children处理
* @param arr [Array] 被处理的数组
* @param group_key [String] 分组字段,默认值为exchange,直接取下标
* @param children [String] 分组之后,名称,默认children
* @param header [String] 前缀
*/
export function formatSelectMmProductData (arr, group_key = 'exchange', children = 'children', header = '') {
let map = {}
let res = []
for (let i = 0; i < arr.length; i++) {
let ai = arr[i]
if (!map[ai[group_key]]) {
map[ai[group_key]] = [ai]
} else {
map[ai[group_key]].push(ai)
}
}
Object.keys(map).forEach(key => {
let pros = []
map[key].forEach(k=>{
// 最内层id设置
if(!k.id){
k.id = k.exchange+k.type+k.product
}
pros.push(k)
})
const obj = {}
obj[group_key] = key
obj[children] = pros
obj['id'] = header+key
obj['text'] = key
res.push(obj)
})
return res
}
组织两层数据整理,首先(按第一个统计维度)整理出第一层,并用childTmp记录该层的数据条目;再遍历childTmp,(按第二个统计维度)整理出第二层
// 构造数据,并设置展开列
let rett = formatSelectMmProductData(
this.mainTradeDealedTableData,
'exchange',
'childTmp'
)
this.expandRowKeys = []
rett.forEach(r => {
// this.expandRowKeys.push(r.id) // 展开列暂不设置
r.children = formatSelectMmProductData(
r.childTmp,
'type',
'children',
r.exchange
)
})
结合业务场景:el-table树形数据的处理
-
数据列表必须拥有children作为子节点
-
row-key需设置唯一id
-
expand-row-keys设置展开列,id取row-key指定的字段
<el-table :data="tableData" size="mini" height="100%" border row-key="text" :expand-row-keys="expandRowKeys" > ... </el-table>
三、el-table合计数据处理
el-table合计列设置:
show-summary
:summary-method="getSummariesDetail"
另注意el-tab中首次合计行不显示问题,在updated中设置this.$refs.cashFutureDataTable.doLayout()
// columns为列设置,data为数据列表,进行纵向横向处理,因此遍历两遍
// 结果为构造出最后一行(合计行)对应每一列的数据
getSummariesDetail (param) {
const { columns, data } = param
const sums = []
console.log(7777, 'ccc', columns, data)
columns.forEach((column, index) => {
if (index === 0) {
sums[index] = '【合计】xxxxxx'
return
}
// 对指定字段进行求合
if (['hedging_ratio'].indexOf(column.property) !== -1) {
return
}
// 对data进行筛选
const values = data.map(item => {
if (
['x1', 'x2', 'x3'].indexOf(item.variety_name) !==
-1
)
{
return Number(item[column.property])
}
})
if (!values.every(value => isNaN(value))) {
sums[index] = values.reduce((prev, curr) => {
const value = Number(curr)
if (!isNaN(value)) {
return prev + curr
} else {
return prev
}
}, 0)
} else {
sums[index] = ''
}
})
// 个别需要依赖自身已得结果的计算
sums[5] = -1 * Number(sums[4]) / Number(sums[3])
// 数值格式化
sums.forEach((o, index)=>{
sums[index] = this.weightFormatter(o)
})
return sums
},
四、el-table合并单元格数据处理
el-table合并单元格设置 :span-method="arraySpanMethod"
arraySpanMethod ({ row, column, rowIndex, columnIndex }) {
let rowspan =
column.property === 'variety_name'
? this.mergeObj[column.property][rowIndex]
: 1
return {
rowspan: rowspan,
colspan: 1
}
},
组织合并数据mergeObj
// 数据统计:数据列表中相同数据(当然一般处理排序之后的数据),纵向合并单元格
getMergeObj (list) {
this.mergeObj = {}
// 标记
let mack = 0
for (const key in list[0]) {
this.mergeObj[key] = []
mack = 0
list.forEach((item, index) => {
if (index === 0) {
this.mergeObj[key].push(1)
} else {
if (item[key] === list[index - 1][key] && item[key]) {
this.mergeObj[key][mack] += 1
this.mergeObj[key].push(0)
} else {
mack = index
this.mergeObj[key].push(1)
}
}
})
}
console.log('-合并对象:', this.mergeObj)
},
// 输出数据,用于span-method中合并
{
"id": [ 1,1,1,1,1,1,1,1 ],
"depart": [ 3,0,0,1,1,1,1,1 ],
"type": [ 1,1,1,1,1,1,1,1 ],
"name": [ 1,1,1,1,1,1,1,1 ],
"age": [ 1,1,1,1,1,1,1,1 ]
}
五、el-table数据量多大且不分页的处理:
t.zoukankan.com/liangtao999… www.cnblogs.com/wanghaoran5…
排查问题:卡慢,由于大量的虚拟dom和真实dom
解决方案:巧妙的dom操作-只渲染可视化的dom,根据列表中数据数量*height计算该区域的高度,使用空节点撑出高度,计算滚动条滚动的top位置,然后把列表放在这里(解决方法为去掉无用dom,只渲染可视化的dom)
六、自定义table
自定义table+treeMenu,横纵锁定cell进行处理
tree部分则采用递归组件形式,通过数据中children判断是否有子节点,level判断当前数据的层次
<div class="vant-table" ref="vantTableRef">
<div class="table_th">
<div
ref="table_th"
v-for="(item, index) in option.column"
:key="index"
:style="{
'flex-grow': item.prop !== 'name' ? 1 : 0,
width: item.prop === 'name' ? firstWidth + 'px' : 0
}"
>
<div v-if="!isArrow">{{ item.label }}</div>
<div v-else>
<div v-if="item.prop == 'name'">
{{ item.label }}
</div>
<div v-else>
<Arrow
ref="fxpxSort"
:name="item.label"
code="fxpx"
@load="load($event, item, index)"
></Arrow>
</div>
</div>
</div>
<div :style="{ width: lastWidth + 'px' }"></div>
<!-- <div style="width: 10px" v-if="isToggle"></div> -->
</div>
<div :key="i" v-for="(item, i) in tableData">
<div class="table_td" ref="table_td" @click="toggle(item)">
<div
v-for="(context, index) in option.column"
:key="index"
class="td"
:style="{
'flex-grow': context.prop !== 'name' ? 1 : 0,
width: context.prop === 'name' ? firstWidth + 'px' : 0
}"
>
<span v-if="context.prop !== 'name' && context.prop !== 'count'">
<span v-if="context.prop === 'delta1'">
{{
commonUtils.stringFormatUtil.decimalMoneyFormat(
item['delta'],
2
)
}}</span
>
<span
v-else-if="
context.prop === 'position_vega' || context.prop === 'gamma'
"
:style="{
color: !item['limit']
? 'black'
: Math.abs(item['position_vega']) > item['limit'] ||
Math.abs(item['gamma']) > item['limit']
? 'red'
: 'green'
}"
>
{{
commonUtils.stringFormatUtil.decimalMoneyFormat(
item[context.prop],
2
) === '-0.00'
? 0
: commonUtils.stringFormatUtil.decimalMoneyFormat(
item[context.prop],
2
)
}}</span
>
<span v-else>
{{
item[context.prop] || item[context.prop] === 0
? commonUtils.stringFormatUtil.decimalMoneyFormat(
item[context.prop],
2
)
: '-'
}}</span
>
</span>
<span v-if="context.prop == 'name'">
<div v-if="item.expand" class="el-icon-arrow-down"></div>
<div v-else class="el-icon-arrow-up"></div>
{{ IsRank ? i + 1 + '.' + item[context.prop] : item[context.prop] }}
</span>
<span v-if="context.prop == 'count'">
{{
commonUtils.stringFormatUtil.decimalMoneyFormat(
item[context.prop],
0
)
}}
</span>
</div>
<div :style="{ width: lastWidth + 'px' }"></div>
</div>
<treeMenu
:level="2"
:firstWidth="firstWidth"
:lastWidth="lastWidth"
:tableData="item.children"
:option="option"
></treeMenu>
</div>
</div>
表格结构
GammaOption: {
column: [
{
label: '板块',
prop: 'name'
},
{
label: '金额',
prop: 'amount'
},
{
label: '重量',
prop: 'weight'
}
]
},