vue + table原生实现表格单元列列宽可重置

33 篇文章 1 订阅
29 篇文章 1 订阅
const tableMixin = {
  data() {
    return {
      dragState: {}, // 记录子表的列宽移动的一些数值
      dragging: false // 子表是否在重置列宽
    }
  },
  methods: {
    handleMouseMove(event) {
      let target = event.target
      while (target && target.tagName !== 'TH') {
        target = target.parentNode
      }
      if (!this.dragging) {
        const rect = target.getBoundingClientRect()
        const bodyStyle = document.body.style
        if (rect.width > 12 && rect.right - event.pageX < 8) {
          // 拖拽的鼠标样式
          bodyStyle.cursor = 'col-resize'
        } else if (!this.dragging) {
          bodyStyle.cursor = ''
        }
      }
    },
    handleMouseOut() {
      document.body.style.cursor = ''
    },
    handleMouseDown(event) {
      // 开始拖拽
      this.dragging = true
      // 当前拖拽的列所在的表格
      let tableEl = event.target
      // 当前所在列(单元格)
      let thEL = event.target
      while (tableEl && tableEl.tagName !== 'TABLE') {
        tableEl = tableEl.parentNode
      }
      // 获取列宽拖拽的显示线(拖拽线)
      const resizeProxy = tableEl.querySelector('.table-column-line')
      while (thEL && thEL.tagName !== 'TH') {
        thEL = thEL.parentNode
      }
      const columnRect = thEL.getBoundingClientRect()
      thEL.classList.add('noclick')
      this.dragState = {
        startMouseLeft: event.clientX, // 鼠标开始的地方
        columnWidth: columnRect.width // th开始拖拽的宽度
      }
      resizeProxy.style.top = tableEl.getBoundingClientRect().top + 'px'
      // resizeProxy.style.height = tableEl.getBoundingClientRect().height + 'px'
      resizeProxy.style.left = this.dragState.startMouseLeft + 'px'
      resizeProxy.classList.remove('dn')
      document.onselectstart = function() {
        return false
      }
      document.ondragstart = function() {
        return false
      }
      const handleMouseMove = event => {
        // 拖拽中,拖拽线与鼠标的位置同步
        resizeProxy.style.left = event.clientX + 'px'
      }
      const handleMouseUp = () => {
        if (this.dragging) {
          // 拖拽完毕
          const { startMouseLeft, columnWidth } = this.dragState
          const finalLeft = parseInt(resizeProxy.style.left, 10)
          const columnWidthDiff = finalLeft - startMouseLeft
          const finalColumnWidth = columnWidthDiff + columnWidth
          const columnMinWidth = parseInt(thEL.style.minWidth, 10)
          thEL.style.width = finalColumnWidth + 'px'
          // 当单元格宽度改变时 表格宽度也进行改变: 1)有最小宽度时宽度改变了 2)无最小宽度时
          if (
            (columnMinWidth && finalColumnWidth >= columnMinWidth) ||
            !columnMinWidth
          ) {
            tableEl.style.width =
              columnWidthDiff + tableEl.clientWidth + 'px'
          }
          document.body.style.cursor = ''
          this.dragging = false
          this.dragState = {}
          resizeProxy.classList.add('dn')
        }

        document.removeEventListener('mousemove', handleMouseMove)
        document.removeEventListener('mouseup', handleMouseUp)
        document.onselectstart = null
        document.ondragstart = null
        setTimeout(function() {
          thEL.classList.remove('noclick')
        }, 0)
      }

      document.addEventListener('mousemove', handleMouseMove)
      document.addEventListener('mouseup', handleMouseUp)
    }
  }
}
export default tableMixin

【表格使用】

// 引入刚刚写的mixin
import tableMixin from './tableMixin'
// 引入混合
 mixins: [tableMixin]
// 在th表头写入
class="table-column-line"
 @mousemove="handleMouseMove"
 @mouseout="handleMouseOut"
 @mousedown="handleMouseDown"

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Vue3 中实现列拖拽功能可以使用原生的拖拽事件来实现,具体步骤如下: 1. 在表格头部的每一列上绑定 `draggable="true"` 属性,使得每一列可以被拖拽。 2. 监听表格头部的每一列的 `dragstart` 事件,记录当前拖拽的列的索引。 3. 监听表格头部的每一列的 `dragover` 事件,并阻止默认行为,以允许放置。 4. 监听表格头部的每一列的 `drop` 事件,获取当前拖拽的列的索引,并交换其与目标列的位置。 以下是一个示例代码: ```vue <template> <table> <thead> <tr> <th v-for="(item, index) in tableColumns" :key="item.id" :draggable="true" @dragstart="dragStart(index)" @dragover.prevent @drop="dropHandler(index)"> {{ item.title }} </th> </tr> </thead> <tbody> <!-- 表格内容 --> </tbody> </table> </template> <script> export default { data() { return { tableColumns: [ { id: 1, title: '列1' }, { id: 2, title: '列2' }, { id: 3, title: '列3' }, ], dragingColumnIndex: null, }; }, methods: { dragStart(index) { this.dragingColumnIndex = index; }, dropHandler(index) { if (index !== this.dragingColumnIndex) { // 交换列顺序 [this.tableColumns[index], this.tableColumns[this.dragingColumnIndex]] = [this.tableColumns[this.dragingColumnIndex], this.tableColumns[index]]; } }, }, }; </script> ``` 在这个示例代码中,我们使用了 `dragingColumnIndex` 来记录当前拖拽的列的索引,然后在 `dropHandler` 中交换拖拽列和目标列的位置。注意,在 `dragover` 事件中使用 `prevent` 修饰符阻止默认行为,以允许 `drop` 事件触发。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值