关于el-table-v2无法在触摸屏上进行滚动的问题

引言

最近在工作上为了实现表格大量数据的显示,然后使用了el-table-v2组件,在调试过程中很顺利的把所有功能实现了,后面到生产过程中发现设备只能使用触摸屏,无法使用鼠标键盘,el-table-v2的滚动条无法适用于触摸屏,后面改为使用touch的方式处理滚动。

本项目使用Vue3、TS、element-plus

实现

1.了解触摸touch事件

触摸事件 - Web API 接口参考 | MDN

为了给基于触摸的用户界面提供高质量的支持,触摸事件提供了在触摸屏或触控板上解释手指(或触控笔)活动的能力。

触摸事件接口是较为底层的 API,可为特定程序提供多点触控交互(比如双指手势)的支持。多点触控交互开始于一个手指(或触控笔)开始接触设备平面的时刻。随后其他手指也可触摸设备表面,并随意进行划动。当所有手指离开设备平面时,交互结束。整个交互期间,程序接收开始、移动、结束三个阶段的触摸事件。

触摸事件与鼠标事件类似,不同的是触摸事件还提供同一表面不同位置的同步触摸。TouchEvent 接口将当前所有活动的触摸点封装起来。Touch 接口表示单独一个触摸点,其中包含参考浏览器视角的相对坐标。

在MDN中查看了Touch事件发现可以利用其中三个事件实现滚动条的定位。

touchstart 事件在一个或多个触点与触控设备表面接触时被触发。

touchmove 事件在触点于触控平面上移动时触发。

touchend 事件在一个或多个触点从触控平面上移开时触发。

// 开始
ontouchstart = (event) => {};

// 移动
ontouchmove = (event) => {};

// 结束
ontouchend = (event) => {};

2.在虚拟表格中使用touch监听

在项目中虚拟表格需要以自适应的方式撑满容器,所有又使用了尺寸自适应el-auto-resize,具体请看以下html代码:

  <div style="width: 100%;height: 100%;" @touchstart="touchstart($event)" @touchmove="touchmove($event)"
    @touchend="touchend($event)">
    <el-auto-resizer>
      <template #default="{ width }">
        <el-table-v2 ref="tableRef" :columns="columns" :width="width" :height="670" :row-height="rowHeight"
          :data="data">
          <template #empty>
            <div></div>
          </template>
        </el-table-v2>
      </template>
    </el-auto-resizer>
  </div>

整个表格组件由div包裹,在div上监听touch的三个事件,达到监听触摸在表格上的X,Y点位。

3.监听事件具体实现

开始触摸时获取起始点位,移动过程中通过当前点位与起始点位的差值对滚动位置进行调整,结束时保存当前滚动位置。具体代码实现如下:

const tableRef = ref<any>()
const rowHeight = ref(30)
let scrollTable = 0
let scrollStart = 0
const touchstart = (event) => {
  scrollStart = event.changedTouches[0].clientY
}
const touchmove = (event) => {
  if (!tableRef.value || !tableRef.value.$el) {
    return
  }
  const el: Element = tableRef.value.$el
  let scroll = scrollTable + scrollStart - event.changedTouches[0].clientY
  const tableScroll = el.querySelector('.el-vl__wrapper')?.clientHeight
  if (!tableScroll) {
    return
  }
  if (scroll > (data.length * rowHeight.value) - tableScroll) {
    scroll = (data.length * rowHeight.value) - tableScroll
  }
  if (scroll < 0) {
    scroll = 0
  }
  tableRef.value.scrollToTop(scroll)
}
const touchend = (event) => {
  if (!tableRef.value || !tableRef.value.$el) {
    return
  }
  const el: Element = tableRef.value.$el
  scrollTable = scrollTable + scrollStart - event.changedTouches[0].clientY
  const tableScroll = el.querySelector('.el-vl__wrapper')?.clientHeight
  if (!tableScroll) {
    return
  }
  if (scrollTable > (data.length * rowHeight.value) - tableScroll) {
    scrollTable = (data.length * rowHeight.value) - tableScroll
  }
  if (scrollTable < 0) {
    scrollTable = 0
  }
}

rowHeight :虚拟表中每行所占的高度。

scrollTable :当前滚动条位置。

scrollStart :触摸起始位置。

需要注意的是当前滚动条位置scrollTable不能小于0且不能超出虚拟表格内容总高度减去当前表格显示高度,因为当前表格显示高度不占用滚动条的范围。

------------------------------------------------------------------------------------

2023/04/10 11:17

wuming

------------------------------------------------------------------------------------

后续

在上机之后触屏滚动能正常使用,但是滚动条无法拖动,由于使用的是虚拟表格,所以表格中行数很长,仅靠滑动去找数据的话非常麻烦,后面找了一些资料,没有找到能控制滚动条的方法。

在element plus滚动条组件中看到了这一条

觉得可以利用滑块的方式控制滚动。话不多说,具体实现如下:

1.使用Slider 滑块

在表格下面使用滑块,通过滑块拖动的方式控制表格滚动条位置,有一些需要注意的地方:

1.滑块滑动后需要修改表格滚动的当前位置值和将表格滚动到滑块移动位置

2.表格滑动后也需要修改滑块的值,通过表格中的scroll事件实现

由于现在滑块还处在表格下方,我的想法是将表格摆到表格右侧,然后从上到下拖动,模拟滚动条效果。通过css和js修改滑块的显示值和背景颜色,表现出从上到下的效果。

将上面实现过了的代码进行改造后就变成了这样:

const value = ref(0)
const max = ref(0)
const formatTooltip = (value: number) => {
  return `${parseInt((max.value - value) / max.value * 10000 + '') / 100}% `
}
const inputSlider = (value: number) => {
  tableRef.value.scrollToTop(max.value - value)
  scrollTable = max.value - value
}

const scroll = ({ scrollTop }) => {
  value.value = max.value - scrollTop
}
const touchmove = (event) => {
  if (!tableRef.value || !tableRef.value.$el) {
    return
  }
  const el: Element = tableRef.value.$el
  let scroll = scrollTable + scrollStart - event.changedTouches[0].clientY
  const tableScroll = el.querySelector('.el-vl__wrapper')?.clientHeight
  if (!tableScroll) {
    return
  }
  if (scroll > (data.length * rowHeight.value) - tableScroll) {
    scroll = (data.length * rowHeight.value) - tableScroll
  }
  if (scroll < 0) {
    scroll = 0
  }
  tableRef.value.scrollToTop(scroll)
  // 以上代码和上述实现中的代码未作修改,仅增加该行
  value.value = max.value - scroll
}
<div class="main">
    <div class="table" @touchstart="touchstart($event)" @touchmove="touchmove($event)"
      @touchend="touchend($event)">
      <el-auto-resizer>
        <template #default="{ width }">
          <el-table-v2 ref="tableRef" :columns="columns" :width="width" :height="640" :row-height="rowHeight"
            :data="data" scrollbar-always-on @scroll="scroll">
            <template #empty>
              <div></div>
            </template>
          </el-table-v2>
        </template>
      </el-auto-resizer>
    </div>
    <el-slider class="slider" :vertical="true" height="585px" v-model="value" :max="max" :format-tooltip="formatTooltip"
      placement="left" @input="inputSlider" />
  </div>
.main {
  width: 100%;
  height: 100%;
  display: flex;

  .table {
    width: 100%;
    height: 100%;

    :deep(.el-virtual-scrollbar) {
      display: none;
    }
  }

  .slider {
    padding-top: 50px;

    :deep(.el-slider__runway) {
      background-color: #409eff;
    }

    :deep(.el-slider__bar) {
      background-color: #e4e7ed;
    }
  }

}

然后基本上所有需求功能已经全部实现,有什么问题的话可以一起交流一下。谢谢!!!

------------------------------------------------------------------------------------

2023/04/11 15:59

wuming

------------------------------------------------------------------------------------

  • 13
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值