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

看起来是vue的语法,我在vue3下面初步试了,还没成功

url  https://mp.weixin.qq.com/s/5_EQjUGMrom7Da-T-gzlKQ

 

 

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>

 

 

  <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 来隐藏原生滚动条,但确保滚动功能仍然有效。

更新兼容手机拖拽功能

 

<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';
    });
  }
}

 

因之前代码只对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'; }); }}

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

 

posted @ 2024-07-18 10:23  hjswlqd  阅读(1281)  评论(0编辑  收藏  举报