• 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上的鼠标拖拽,也支持了手机上的触摸拖拽。

  • 相关阅读:
    SpringBoot集成EasyExcel快速人们
    MyLife - Docker安装rabbitmq
    机器学习常识:初学者应该知道的10 大机器学习算法
    拼多多API_根据ID取商品详情
    探析共享股东模式:创新的商业模式引领共享经济发展
    【react-native】关于ios与android的环境搭建
    《Python 计算机视觉编程》学习笔记(一)
    Java中如何遍历HashMap呢?
    209.Flink(四):状态,按键分区,算子状态,状态后端。容错机制,检查点,保存点。状态一致性。flink与kafka整合
    深入解析Windows操作系统——概念和工具
  • 原文地址:https://blog.csdn.net/weixin_45049746/article/details/139277223