最近遇到了antd 表格展开行的需求,然后遇到了非常恶心的事情,首先官方文档中只有expandedRowRender可以渲染组件,此为渲染层,这个属性方法有四个参数function(record, index, indent, expanded),分别为当前行,下标,缩进,当前行状态(true为展开,false为关闭)。这个方法点击每个展开行都会执行一遍,默认不管是关闭和打开。
然后我的需求是点击展开行要用到当前行id去请求一个接口渲染图表,此为异步操作,我一开始不想请求数据的逻辑写在expandedRowRender里,我是用onExpan方法,控制点击谁请求谁(否则expandedRowRender里面执行会把所有点击过的行全部请求一遍,对,就是这么恶心,接口会被泛用,肯定不能这么消耗接口请求),然后把数据传到expandedRowRender。然后发现expandedRowRender里的东西总是在我数据传给他之前就渲染了,我的数据到它那里总是慢一步,我想这是异步操作的原因。然后就卡了。
后来我想先把数据展示要紧把请求接口的数据写在expandedRowRender,没想到他根本都不渲染。这下把我给急坏了。然后我使用async/await,想把请求数据转换成同步操作,但是js线程里,await后面操作还是要慢一点,这样我总是不能同步把数据渲染出来。
如图
async2()之后并没有打印async1 end 。而是走了下面。纵使我把接口处理成同步的拿到了数据,拿到数据后进行数据处理这步还是在渲染之后,这下可把我恶心坏了。怎么办呢,
到这一步我决定吧图表塞在可异步处理数据的table里面,然后配合使用onExpandedRowsChange 、expandedRowKeys,expandedRowRender中的expanded只展示我当前点击的那个。然后将得到处理的数据重新set到table里面。但因为渲染图表的table中data此时并不和当前行record有所关联,当我点击其他行时候,会展示上一个点击的行的数据,所以我们每次新点击一行后都要全局置空一下。
我的代码
<Table columns={columns} dataSource={data} bordered
pagination={pageData}
rowClassName="editable-row"
pagination={pageData}
size="small"
rowExpandable = {(record) => {
return true
}}
expandedRowKeys={rkey}
onExpandedRowsChange = {(expandedRows)=>{
console.log(expandedRows);
let arr = [];
arr.push(expandedRows[expandedRows.length-1]);
setrkey(arr);
}}
onExpand={(status,record)=>{
if(status){
setData2([]);
}
}}
expandedRowRender = {(record, index, indent, expanded) => {
//console.log(record, index, indent, expanded);
let columns = [];
if(expanded){
columns = [
{
title: '图表',
key: 'date' ,
render: (text, record, index) => {
return (
<div>
<Empty style={{display:record.time?'none':'block'}}/>
<div id={record.time} style={{width:'100%',height:'270px',display:record.time?'block':'none'}}></div>
</div>
)
},
},
];
var params = {};
if (beginTime != null && beginTime !="") {
params.startTime = beginTime;
}
if (endTime != null && endTime !="") {
params.endTime = endTime;
}
let arr = [...data2];//为了关闭的时候不再执行接口
//console.log(arr);
if(arr.length==0){
AssetScoringCharts(params,context.ProbeKey,record.assetId).then(res=>{
let option = {};
const timeEchart=new Date().getTime()+record.assetId;
option.arr = res;
option.time = timeEchart;
setData2([option]);
const Ydata = [];
if(option.arr.length>0){
Array.from(option.arr, function (v, i) {
let a=v.score?v.score:'-'
Ydata.push([v.samplingTime,a]);
});
}
let option1 = {
color: ["#0CC9FC"],
title: {
text: '',
textStyle: {
fontSize: 14,
color: "#0CC9FC"
},
},
tooltip: {
trigger: 'axis'
},
legend: {
right: '8%',
orient: 'vertical',//竖向排列
},
grid: {
left: '7%',
right: '7%',
bottom: '8%',
containLabel: true
},
xAxis: {
splitLine: {//分割线样式
lineStyle: {
// 使用深浅的间隔色
color: '#F0F0F0'
}
},
axisLine: {
lineStyle: {
color: "#2A195B"
},
//show: false//坐标轴是否显示
},
type: 'category',
boundaryGap: false,
//data:Xdata
//data: ['2016-1', '2016-2', '2016-3', '2016-4', '2016-5', '2016-6', '2016-7', '2016-8', '2016-9', '2016-10', '2016-11', '2016-12']
},
yAxis: {
type: 'value',
splitLine: {
lineStyle: {
// 使用深浅的间隔色
color: '#F0F0F0'
}
},
axisLine: {
lineStyle: {
color: "#2A195B"
},
show: false
},
},
series: [
{
name:'分数',
type: 'line',
// areaStyle: {},
areaStyle: {
color: 'rgba(12,201,252,0.30)'
},
data: Ydata
}
]
}
let myChart = echarts.init(document.getElementById(timeEchart));
// 绘制图表
myChart.setOption(option1);
}).catch(err=>{
})
}
}
return <Table columns={columns} dataSource={data2} pagination={false} />;
}}
/>
当然可以把可展开行内容变成一个引入的控件,这样也可以。