UI交互统一之表格高度自适应解决方案
近期UI对产品交互制定了一些规范,其中就有表格高度自适应一项
tip: Vue写法与react写法稍有差异但代码解读一致,react写在后面;
本方案主要采用css flex
+ vue watch监听计算 (react useEffect 同理,但在封装的table组件内可以直接在请求得到数据后执行)
首先,内容布局需使用flex
做内容自适应
Vue表格相关代码如下(默认父元素已使用display: flex; flex-direction: column
布局):
// template
<div class="table-wrap" :style="{ maxHeight: `${tableOffsetHeight + 54}px` }">
<Table
ref="table"
height="100%"
:table-data="list"
:need-index="false"
custom-empty-text="您暂时没有可管理的项目"
:params="tableColumns"
:table-loading="tableLoading">
</Table>
</div>
// javascript
private tableOffsetHeight = 0;
@Watch('list') private watchList() {
setTimeout(() => {
// .el-table__body 为element table实际内容高度
this.tableOffsetHeight = (document.querySelector('.el-table__body') as any).offsetHeight;
}, 0);
}
// css
.table-wrap {
flex: auto;
min-height: 400px; // ui 规范的最少要有400的高度显示
}
代码解读
- 当
table-wrap
为flex: auto
布局时会跟随页面大小自适应填充内容 - 其次给
flex
设置最小高度与最大高度时,则能够限制flex
的填充范围 - 在每次表格内容更新时,重新获取表格内容高度+表格
Header
高度,给其重新设置max-height
React antd表格相关代码示例
// html
<div className={cs(className, layoutFixedBox && styles.layoutFixedBox)} ref={ref}>
<Table
style={{ maxHeight: `${tableOffsetHeight + 55}px` }}
{...props}
rowKey={rowKey}
bordered={bordered}
loading={data.loading}
dataSource={data.dataSource}
pagination={false}
scroll={scroll}
showSorterTooltip={false}
rowSelection={rowSelection}
childrenColumnName={childrenColumnName}
expandable={{
expandedRowKeys,
onExpand,
...expandable,
}}
onChange={handleSorterChange}
>
{/* 如果传入是columns则使用columns 否则渲染children(与table用法一致) */}
{(columns && Array.isArray(columns) && renderColumnNode(columns)) || children}
</Table>
</div>
// javascript
const [tableOffsetHeight, setTableOffsetHeight] = useState(0);
...
// 请求接口
const { dataSource, count } = await onFetch(fetchParams);
setTimeout(() => {
// .ant-table-tbody 为antd table实际内容高度
const antTableBody: any = document.querySelector('.ant-table-tbody');
setTableOffsetHeight(antTableBody.offsetHeight);
}, 0);
// css
.layoutFixedBox {
flex: 1;
display: flex;
flex-direction: column;
:global {
.ant-table-wrapper {
flex: auto;
// height: 0;
min-height: 400px;
}
}
}