场景描述
PC端网页开发时,表格的CRUD是我们逃不掉的宿命。在渲染表格时,往往是默认
10 | 15 | 20
作为表格请求的长度,但是由于显示屏和电脑设置等等导致的差异,有时候会导致表格下方出现大量空白。这时候我们可以根据屏幕的剩余空间去动态改变pageSize
的值,以达到较好的效果。因为无法保证每一行都是占用一行,所以出现滚动条是很正常的。
具体实现
计算每页数量
基于
el-table
的自定义指令,el-table
每一行默认的高度为40
;根据自己的场景,表格距离底部的一个距离,一般底部都是有分页组件的。实现resize
函数,在该函数内实现表格的第一次请求。
// 默认表格每一行的高度
const defaultRowHeight = 40
// pageination的高度50 + mg-top:12 + 页面的padding20
const bottomHeight = 82
const resize = (el, bind) => {
const { value } = bind
const {
params,
getTableData,
} = value
const height = window.innerHeight - el.getBoundingClientRect().top
el.style.height = 'auto'
// 获取表头的高度
const elTableHeaderDom = el.querySelector('.el-table__header-wrapper')
// delSize是除去表头的行数
const delSize = elTableHeaderDom && Math.ceil(elTableHeaderDom.clientHeight / defaultRowHeight)
// 分页表格
const autoSize = Math.ceil((height - bottomHeight) / defaultRowHeight) - delSize
params[sizeKey] = autoSize <= 0 ? 1 : autoSize
getTableData && getTableData()
}
监听屏幕变化,动态改变 size
const setObserver = (el, bind) => {
el.resizeObserver = new ResizeObserver(
// 这是lodash库的节流函数
_.throttle(() => {
resize(el, bind);
}, 500)
);
// 监听body的变化
el.resizeObserver?.observe(document.body);
}
清除observer
const clearObserver = el => {
el.resizeObserver?.disconnect()
delete el.resizeObserver
}
指令实现
注意
keep-alive
的组件
export default {
mounted(el, bind) {
setObserver(el, bind)
},
beforeUpdate(el, bind) {
// keep-alive组件activated
if (el.isConnected && !el.resizeObserver) {
setObserver(el, bind)
}
// keep-alive组件deactivated
if (!el.isConnected && el.resizeObserver) {
clearObserver(el)
}
},
// 非keep-alive组件卸载
beforeUnmount(el) {
clearObserver(el)
},
}
完整代码
为了避免重复提交请求,新增个判断 – 2024.2.2
/**
* @description: 表格填充剩余空间
* @param {Object} value - 指令的绑定值
* @param {Object} value.params - 请求列表的参数-必传
* @param {String} value.sizeKey - 请求列表的参数-可选,默认为size
* @param {Function} value.getTableData - 请求列表的方法-可选-根据具体页面而定,因为涉及到缓存
* eg:
* <el-table v-fill-space="{ params, sizeKey: 'pageSize', getTableData }"></el-table>
*/
import _ from 'lodash';
// 默认表格每一行的高度
const defaultRowHeight = 40
// pageination的高度50 + mg-top:12 + 页面的padding20
const bottomHeight = 82
// 避免重复发送相同请求
let isRepeatSubmit = false
// 重新计算高度
const resize = async (el, bind) => {
const { value } = bind
const {
params,
sizeKey = 'size',
getTableData,
} = value
const height = window.innerHeight - el.getBoundingClientRect().top
el.style.height = 'auto'
// 获取表头的高度
const elTableHeaderDom = el.querySelector('.el-table__header-wrapper')
// delSize是除去表头的行数,如果表头有多行,需要传入delSize
const delSize = elTableHeaderDom && Math.ceil(elTableHeaderDom.clientHeight / defaultRowHeight)
// 分页表格
const autoSize = Math.ceil((height - bottomHeight) / defaultRowHeight) - delSize
params[sizeKey] = autoSize <= 0 ? 1 : autoSize
if (getTableData && !isRepeatSubmit) {
isRepeatSubmit = true
await getTableData()
isRepeatSubmit = false
}
}
// 设置observer
const setObserver = (el, bind) => {
el.resizeObserver = new ResizeObserver(
_.throttle(() => {
resize(el, bind);
}, 500)
);
// 监听body的变化,不可监听el的变化
el.resizeObserver?.observe(document.body);
}
// 清除observer
const clearObserver = el => {
el.resizeObserver?.disconnect()
delete el.resizeObserver
}
export default {
mounted(el, bind) {
setObserver(el, bind)
},
beforeUpdate(el, bind) {
// keep-alive组件activated
if (el.isConnected && !el.resizeObserver) {
setObserver(el, bind)
}
// keep-alive组件deactivated
if (!el.isConnected && el.resizeObserver) {
clearObserver(el)
}
},
// 非keep-alive组件卸载
beforeUnmount(el) {
clearObserver(el)
},
}