自定义指令代码
Vue.directive(‘tableDrag‘, {
update: function(el,binding,vnode) {
var container=el.parentNode;
var tbody=el.getElementsByClassName(‘el-table__body-wrapper‘)[0];
var thead = el.getElementsByClassName(‘el-table__header-wrapper‘)[0];
// 更新数据时,先还原数据本来的顺序,不然新加载的数据和表头对不上
var trCollection=container.getElementsByTagName("tr");
for (var i = 0; i < trCollection.length; i++) {
var tr=trCollection[i];
if(i==0){
var collection=tr.getElementsByTagName("th");
}else{
var collection=tr.getElementsByTagName("td");
}
if(collection.length>1){
let cellArr=[];
for (let j = 0; j < collection.length; j++) {
let cell=collection[j];
let classNames=cell.className;
let className=classNames.split(" ")[0];
let arr=className.split("_");
if(arr.length){
let index=arr[arr.length-1];
cellArr[index-1]=cell;
}
}
for(let k=0;k<cellArr.length;k++){
tr.insertBefore(cellArr[k],collection[k])
}
}
}
// 列拖拽开始...
if(!container.className.includes(‘drag-table‘))container.className=" drag-table";
thead.onmousedown = function(e) {
const clickX=event.clientX
const rect=event.target.getBoundingClientRect()
const divLeft=rect.left
const divRight=rect.right
//拖动列
if(event.target.tagName=="DIV"&&(clickX>divLeft+5&&clickX<divRight-5)){
//被拖动的th
var ev_th=event.target.parentNode;
var scrollLeft=tbody.scrollLeft
//算出鼠标相对元素的位置
let disX = e.clientX + scrollLeft - ev_th.offsetLeft;
let disY = e.clientY - ev_th.offsetTop;
let thWidthArr = []; // 记录所有的th的宽度,依次累加
let thWidthObj = {}; // 记录所有的th的宽度,依次累加
let finallIndex = 0;//最终的th index
let directionIndex = 0; // 单击的是第几个th
let move=0; // 移动的方向 1-右 2-左
const ths = ev_th.parentNode.children;
var len=ths.length-1;// 删除elementUI最后的class="gutter"的元素
for(let thi = 0;thi<len;thi++){
const itemth = ths[thi];
itemth.index = thi;
thWidthArr.push(itemth.offsetLeft)
}
directionIndex = ev_th.index;
// 以鼠标按下的这个th处,创建一个和th内容一样的div,
const createDiv = document.createElement(‘div‘);
createDiv.id = ‘created-div‘;
container.appendChild(createDiv);
document.onmousemove = (e)=>{
// 用鼠标的位置减去鼠标相对元素的位置,得到元素的位置
let left = e.clientX - disX;
let top = e.clientY - disY;
if(Math.abs(e.clientX - disX - ev_th.offsetLeft)<10){return;}
//绑定元素位置到positionX和positionY上面
//移动当前元素
const thText = ev_th.innerHTML;
createDiv.innerHTML = thText;
createDiv.style.position = ‘absolute‘;
createDiv.style.width = ev_th.offsetWidth + ‘px‘;
createDiv.style.height = ev_th.offsetHeight + ‘px‘;
createDiv.style.background = ‘#666‘;
createDiv.style.lineHeight = ev_th.offsetHeight + ‘px‘;
createDiv.style.textAlign = ‘center‘;
createDiv.style.left = left + ‘px‘;
createDiv.style.top = top + ‘px‘;
finallIndex = 0; //鼠标拖动过程中所停留在的th的index
var distance=createDiv.offsetLeft+scrollLeft
var i=thWidthArr.length-1;
while(i>=0){
if(distance>=thWidthArr[i]){
finallIndex=i;
break;
}
i--;
}
};
document.onmouseup = (e) => {
if(directionIndex<finallIndex){move=1}//右移
else if(directionIndex>finallIndex){move=2}//左移
const th_trs = thead.getElementsByTagName(‘tr‘);
const td_trs = tbody.getElementsByTagName(‘tr‘);
container.removeChild(createDiv);
// 取消鼠标拖动和鼠标抬起事件
document.onmousemove = null;
document.onmouseup = null;
// 如果没有进行拖动操作(鼠标点下就抬起)
if(Math.abs(e.clientX - disX- ev_th.offsetLeft)<10){
thWidthArr = [];disX = 0;
return;
}
// 遍历tr,将th和td放到最终的位置上
var itemtr=th_trs[0];
if(itemtr.getElementsByTagName(‘th‘).length){
const ths = itemtr.getElementsByTagName(‘th‘);
if(move===1){
itemtr.insertBefore(ths[directionIndex],ths[finallIndex+1]);
}else if(move===2){
itemtr.insertBefore(ths[directionIndex],ths[finallIndex]);
}
}
for(let i = 0;i<td_trs.length;i++){
const itemtr = td_trs[i];
if(itemtr.getElementsByTagName(‘td‘).length){
const tds = itemtr.getElementsByTagName(‘td‘);
if(move===1){
itemtr.insertBefore(tds[directionIndex],tds[finallIndex+1]);
}else if(move===2){
itemtr.insertBefore(tds[directionIndex],tds[finallIndex]);
}
}
}
// 重置thWidthArr和disX
thWidthArr = [];disX = 0;
};
}
};
}});
全局css
.drag-table{ position: relative; -moz-user-select: none; -khtml-user-select: none; user-select: none; } .drag-table th{ cursor: move; }
模板绑定指令
<el-table v-table-drag border :data="tableData" @sort-change="sortChange" ">......</el-table>
注意事项
原文:https://www.cnblogs.com/LunuZ/p/13900168.html