Vue3 自定义指令让元素自适应高度,el-table在可视区域内滚起来

我始终坚持,前端开发不能满足于实现功能,而是需要提供优秀的交互与用户体验。即使没有产品没有UI的小项目,也可以自己控制出品质量,做到小而美。所以前端们不仅仅需要了解框架如何用,还要学习一些设计、交互、体验的知识,在一堆雷同的产品中脱颖而出。

哦,扯远了,因为今天想记录的这个功能是一个小小的体验提升,有感而发了。

表格行数较多时会让页面产生滚动条,用户滚动页面的话,上面的搜索条件或者其它内容被卷上去了看不到,不方便对照数据。所以用户的需求是只让表格滚动,其他元素都不要滚。

在这里插入图片描述

el-table滚动条

当el-table 表格所需的高度大于最大高度max-height或者高度height,则会显示一个滚动条。所以我们只需要给el-table固定一个高度,让页面整个高度不要超过窗口高度,就不会把其他元素卷走了。

具体实现

为了表格页面统一,让页码组件停留在页面底部,我们选择设置height,而不是max-height。所以现在的问题就是计算出height的值。

我们可以得到这三个值

  • 窗口高度 pageHeight = window.innerHeight
  • el-table距离窗口顶部偏移量 top = el.offsetTop
  • 底部预留的高度 bottom(这个值是自己设置的)

表格的高度 = 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版本更加简洁清晰。

如果对你有一点帮助,请点个赞吧 👍

  • 8
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

immocha

人生得意须尽欢

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值