vue实现表格列位置的拖拽

首先我们看下最终的交互效果:

此功能是针对vue项目的表格拖拽,以自定义指令的形式来完成交互的.

主要原理的dom节点的交换;

交互思路:

1.首先要获取当前点击的th,并且在页面创建一个大小内容和th一模一样的div.并设置当前div的样式始终随着鼠标.

2.将页面上所有的th的宽度保存到一个数组中(thWidthArr),获取保存下来当前点击的th的index(directionIndex),和鼠标拖动到最后松开的时候所停留的th的index(finallIndex);

3.当鼠标拖拽到确定的位置,将最初始的th和插入到当前位置(通过directionIndex和finallIndex来确定)

完整代码请移步:https://github.com/slailcp/vue-dragTable 哦

然后就完成啦,话不多说上代码

自定义指令名字叫做 "slldrag" 使用的时候就是v-slldrag,

Vue.directive("slldrag",{
    bind:(el)=> {
      let op = el;  //获取当前元素

      op.onmousedown = (e) => {
        //算出鼠标相对元素的位置
        let disX = e.clientX - op.offsetLeft;
        let disY = e.clientY - op.offsetTop;

        let thWidthArr = []; // 记录所有的th的宽度,依次累加
        let finallIndex = 0;//最终的th index
        let directionIndex = 0; // 单击的是第几个th
        let $insertTh = null;

        $insertTh = e.target; //

        const $th = op.parentNode.children; // 获取所有th
        for(let thi = 0;thi<$th.length;thi++){
          const itemth = $th[thi];
          itemth.index = thi;
          let offsetWidth = 0;
          if(thi === 0){
            offsetWidth=itemth.offsetWidth+offsetWidth; // 如果是第一个th就不进行累加操作
          }else{
            offsetWidth = itemth.offsetWidth+thWidthArr[thi-1]; // 累加th的宽度
          }
          thWidthArr.push(offsetWidth)
        }
        directionIndex = e.target.index;

        // 以鼠标按下的这个th处,创建一个和th内容一样的div,
        const $createDiv = document.createElement('div');
        $createDiv.id = 'created-div';
        document.getElementById('drag-table').appendChild($createDiv);

        document.onmousemove = (e)=>{
          //用鼠标的位置减去鼠标相对元素的位置,得到元素的位置
          let left = e.clientX - disX;
          let top = e.clientY - disY;
          if(Math.abs(e.clientX - disX - op.offsetLeft)<10){return;}
          //绑定元素位置到positionX和positionY上面
          // this.positionX = top;
          // this.positionY = left;

          //移动当前元素
          const thText = op.innerHTML;
          $createDiv.innerHTML = thText;
          $createDiv.style.position = 'absolute';
          $createDiv.style.width = op.offsetWidth + 'px';
          $createDiv.style.height = op.offsetHeight + 'px';
          $createDiv.style.background = '#666';
          $createDiv.style.left = left + 'px';
          $createDiv.style.top = top + 'px';

          finallIndex = 0; //鼠标拖动过程中所停留在的th的index
          if(left<=0){ // // 小于0的时候就等于0
            finallIndex = 0;
          }else if(left>thWidthArr[thWidthArr.length-1]){ // 大于最后一个的时候就最后一个+1
            finallIndex = thWidthArr.length;
          }else{
            for (let i = 0;i<thWidthArr.length;i++){
              if(left >= thWidthArr[i-1] && left <= thWidthArr[i]){
                finallIndex = i;
              }
            }
          }

          // 拖动的时候用红线标识拖动到哪个位置
          /*****************此处dom交互较多,省略省略省略省略省略省略*****************/

        };
        document.onmouseup = (e) => {
          const $tr = document.getElementById('drag-table').getElementsByTagName('table')[0].getElementsByTagName('tr');
          document.getElementById('drag-table').removeChild($createDiv);

          // 鼠标抬起恢复表格的样式
          /*****************此处dom交互较多,省略省略省略省略省略省略*****************/

          // 取消鼠标拖动和鼠标抬起事件
          document.onmousemove = null;
          document.onmouseup = null;

          // 如果没有进行拖动操作(鼠标点下就抬起)
          if(Math.abs(e.clientX - disX- op.offsetLeft)<10){
            thWidthArr = [];disX = 0;
            return;
          }

          // 遍历tr,将th和td放到最终的位置上
          for(let tri = 0;tri<$tr.length;tri++){
            const itemtr = $tr[tri];
            if(itemtr.getElementsByTagName('th').length){
              const $ths = itemtr.getElementsByTagName('th');
              itemtr.insertBefore($insertTh,$ths[finallIndex]);
            }
            if(itemtr.getElementsByTagName('td').length){
              const $tds = itemtr.getElementsByTagName('td');
              itemtr.insertBefore($tds[directionIndex],$tds[finallIndex]);

            }
          }

          // 重置thWidthArr和disX
          thWidthArr = [];disX = 0;

        };
      };
    }
  });

完整代码请移步:https://github.com/slailcp/vue-dragTable 哦

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值