我始终坚持,前端开发不能满足于实现功能,而是需要提供优秀的交互与用户体验。即使没有产品没有UI的小项目,也可以自己控制出品质量,做到小而美。所以前端们不仅仅需要了解框架如何用,还要学习一些设计、交互、体验的知识,在一堆雷同的产品中脱颖而出。
哦,扯远了,因为今天想记录的这个功能是一个小小的体验提升,有感而发了。
表格行数较多时会让页面产生滚动条,用户滚动页面的话,上面的搜索条件或者其它内容被卷上去了看不到,不方便对照数据。所以用户的需求是只让表格滚动,其他元素都不要滚。
当el-table 表格所需的高度大于最大高度max-height或者高度height,则会显示一个滚动条。所以我们只需要给el-table固定一个高度,让页面整个高度不要超过窗口高度,就不会把其他元素卷走了。
为了表格页面统一,让页码组件停留在页面底部,我们选择设置height,而不是max-height。所以现在的问题就是计算出height的值。
我们可以得到这三个值
pageHeight = window.innerHeight
top = el.offsetTop
表格的高度 = pageHeight - top - bottom
OK,可以开始写我们的指令了
import { DirectiveBinding } from 'vue'
export default {
mounted: (el: HTMLElement, binding: DirectiveBinding) => {
setHeight(el, binding)
},
}
// set el-table height
function setHeight(el: HTMLElement, binding: DirectiveBinding) {
const top = el.offsetTop
const bottom = binding?.value?.bottom || 64
const pageHeight = window.innerHeight
el.style.height = pageHeight - top - bottom + 'px'
}
然后加到el-table上
<el-table
:data="tableData"
ref="multipleTable"
v-adaptive
>
刷新页面,表格高度非常合适,页面不滚了。是不是很简单!
但是如果用户缩放页面,表格高度并不会自动变化,页面的滚动条又出来了。。。 看来我们的指令还是不够完善,接下来加入window resize事件
通过window.addEventListener,在表格挂载完成后加入resize事件。
为了让表格在卸载后,及时销毁resize监听事件removeEventListener, 事件通知对象listener不能是一个匿名函数。所以把listener挂在el上,因为HTMLElement类型上没有我们定义的listenenr函数,所以此处扩展了一下类型,这样在使用ts时不会爆红。
import { DirectiveBinding } from 'vue'
interface ExHTMLElement extends HTMLElement {
resizeListener: EventListener
}
export default {
mounted: (el: ExHTMLElement, binding: DirectiveBinding) => {
el.resizeListener = () => {
setHeight(el, binding)
}
setHeight(el, binding)
window.addEventListener('resize', el.resizeListener)
},
unmounted(el: ExHTMLElement) {
window.removeEventListener('resize', el.resizeListener)
}
}
// set el-table height
function setHeight(el: ExHTMLElement, binding: DirectiveBinding) {
const top = el.offsetTop
const bottom = binding?.value?.bottom || 64
const pageHeight = window.innerHeight
el.style.height = pageHeight - top - bottom + 'px'
}
现在再刷新页面,无论怎么缩放窗口,表格都可以自适应高度了。
问题又来了,页面上搜索表单是可以展开收起的,当我展开更多表单搜索时,表格高度没变,页面又可以滚了。所以再加一个钩子 update,完美解决。
// 在绑定元素的父组件
// 及他自己的所有子节点都更新后调用
updated(el, binding, vnode, prevVnode) {},
updated(el: ExHTMLElement, binding: DirectiveBinding) {
setHeight(el, binding)
}
至此,已经满足我的项目使用了。
刚才又想到普通DIV元素也可以用这个指令,稍微修改了下更通用。
// set el-table height
function setHeight(el: ExHTMLElement, binding: DirectiveBinding) {
...
el.style.height = pageHeight - top - bottom + 'px'
el.style.overflowY = 'auto' // 新增加
}
以前也做过Vue2 Element UI的类似指令,不得不说 Vue3版本更加简洁清晰。
如果对你有一点帮助,请点个赞吧