element-ui组件table去除下方滚动条,实现鼠标左右拖拽移动表格

时隔多日,再次遇到值得记录的问题。

需求

项目前端使用vue框架,页面使用element-ui进行页面快速搭建。默认的table组件当表格过长时,下方会出现横向的滚动条,便于用户对表格进行左右滑动。考虑到页面美观问题,滚动条设置的很窄,导致用户使用时不方便进行左右滑动。
现要求,去除表格下方滚动条,用户可直接拖拽表格实现左右滑动功能。
表格设置固定表头和列,实践证明并不影响此功能。

思路

鼠标点击进行拖拽,首先想到鼠标的点击事件,添加mousedownmouseleavemouseupmousemove事件的监听器,实现拖拽效果。通过设置tableBodyWrapper.style.overflow = 'hidden';隐藏原生的滚动条。

实现

要实现拖拽功能,并确保 tableBodyWrapper 可以正确拖拽,需要设置事件监听器和对样式进行一些调整。下面是实现代码:

  <template>
	<div ref="tableContainer" class="table-container">
	    <el-table
	      :data="tableData"
	      style="width: 100%">
	      <el-table-column
	        prop="date"
	        label="日期"
	        width="180">
	      </el-table-column>
	      <el-table-column
	        prop="name"
	        label="姓名"
	        width="180">
	      </el-table-column>
	      <el-table-column
	        prop="address"
	        label="地址">
	      </el-table-column>
	    </el-table>
  	</div>
  </template>

<script>
export default {
  data() {
    return {
      tableData: [{
            date: '2016-05-02',
            name: '王小虎',
            address: '上海市普陀区金沙江路 1518 弄'
          }, {
            date: '2016-05-04',
            name: '王小虎',
            address: '上海市普陀区金沙江路 1517 弄'
          }, {
            date: '2016-05-01',
            name: '王小虎',
            address: '上海市普陀区金沙江路 1519 弄'
          }, {
            date: '2016-05-03',
            name: '王小虎',
            address: '上海市普陀区金沙江路 1516 弄'
          }]
    };
  },
  mounted() {
    this.enableDrag();
  },
  methods: {
    enableDrag() {
      this.$nextTick(() => {
        const tableContainer = this.$refs.tableContainer;
        const tableBodyWrapper = this.$refs.table.$el.querySelector('.el-table__body-wrapper');
        
        if (!tableBodyWrapper) {
          console.error('找不到表体。');
          return;
        }

        let isDown = false;
        let startX, scrollLeft;

        tableBodyWrapper.addEventListener('mousedown', (e) => {
          isDown = true;
          startX = e.pageX - tableBodyWrapper.offsetLeft;
          scrollLeft = tableBodyWrapper.scrollLeft;
          tableBodyWrapper.style.cursor = 'grabbing';
        });

        tableBodyWrapper.addEventListener('mouseleave', () => {
          isDown = false;
          tableBodyWrapper.style.cursor = 'grab';
        });

        tableBodyWrapper.addEventListener('mouseup', () => {
          isDown = false;
          tableBodyWrapper.style.cursor = 'grab';
        });

        tableBodyWrapper.addEventListener('mousemove', (e) => {
          if (!isDown) return;
          e.preventDefault();
          const x = e.pageX - tableBodyWrapper.offsetLeft;
          const walk = (x - startX) * 2; // scroll-fast
          tableBodyWrapper.scrollLeft = scrollLeft - walk;
        });

        // 隐藏滚动条
        tableBodyWrapper.style.overflowX = 'hidden';
      });
    }
  }
};
</script>

<style>
.table-container {
  overflow: hidden;
  white-space: nowrap;
}

.el-table__body-wrapper {
  cursor: grab;
}

.el-table__body-wrapper:active {
  cursor: grabbing;
}
</style>

解释:

  • 获取DOM元素:在this.$nextTick()回调中,通过this.$refs.table.$el.querySelector('.el-table__body-wrapper')获取到实际的表格内容区域的DOM元素。这样就确保我们在对DOM元素进行操作,而不是组件实例。
  • 检查 DOM 元素存在:在 this.$nextTick 中,我们先检查 tableElement 是否存在,然后再查询 tableBodyWrapper
  • 添加错误处理:如果 tableBodyWrapper 没有找到,输出错误信息到控制台。这有助于调试并确保代码的稳健性。
  • 拖拽事件绑定到 tableBodyWrapper:确保拖拽事件绑定在实际可滚动的 tableBodyWrapper 上。
  • 样式调整:使用 tableBodyWrapper 的样式来显示抓手光标,并在拖动时切换光标样式。
  • 隐藏水平滚动条:通过设置 overflowX: hidden 来隐藏原生滚动条,但确保滚动功能仍然有效。

更新兼容手机拖拽功能

因之前代码只对pc端进行实现,手机进行拖拽无反应,现新加入手机拖拽事件。以下是修改后的代码,添加了触摸事件的支持:

<div ref="tableContainer" class="table-container">
  <el-table ref="table">
  </el-table>
</div>

methods: {
  enableDrag () {
    this.$nextTick(() => {
      const tableContainer = this.$refs.tableContainer;
      const tableBodyWrapper = this.$refs.table.$el.querySelector('.el-table__body-wrapper');

      if (!tableBodyWrapper) {
        console.error('Table body wrapper not found.');
        return;
      }

      let isDown = false;
      let startX, scrollLeft;

      // 鼠标事件
      tableBodyWrapper.addEventListener('mousedown', (e) => {
        isDown = true;
        startX = e.pageX - tableBodyWrapper.offsetLeft;
        scrollLeft = tableBodyWrapper.scrollLeft;
        tableBodyWrapper.style.cursor = 'grabbing';
      });

      tableBodyWrapper.addEventListener('mouseleave', () => {
        isDown = false;
        tableBodyWrapper.style.cursor = 'grab';
      });

      tableBodyWrapper.addEventListener('mouseup', () => {
        isDown = false;
        tableBodyWrapper.style.cursor = 'grab';
      });

      tableBodyWrapper.addEventListener('mousemove', (e) => {
        if (!isDown) return;
        e.preventDefault();
        const x = e.pageX - tableBodyWrapper.offsetLeft;
        const walk = (x - startX) * 2; // scroll-fast
        tableBodyWrapper.scrollLeft = scrollLeft - walk;
      });

      // 触摸事件
      tableBodyWrapper.addEventListener('touchstart', (e) => {
        isDown = true;
        startX = e.touches[0].pageX - tableBodyWrapper.offsetLeft;
        scrollLeft = tableBodyWrapper.scrollLeft;
      });

      tableBodyWrapper.addEventListener('touchend', () => {
        isDown = false;
      });

      tableBodyWrapper.addEventListener('touchmove', (e) => {
        if (!isDown) return;
        e.preventDefault();
        const x = e.touches[0].pageX - tableBodyWrapper.offsetLeft;
        const walk = (x - startX) * 2; // scroll-fast
        tableBodyWrapper.scrollLeft = scrollLeft - walk;
      });

      // 隐藏滚动条
      tableBodyWrapper.style.overflowX = 'hidden';
    });
  }
}

在这个代码中,我们为 touchstart, touchendtouchmove 事件添加了相应的处理函数,以支持在手机上的左右拖拽操作。这样既兼容了PC上的鼠标拖拽,也支持了手机上的触摸拖拽。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

懒人w

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值