在使用element-ui 2.x以及vue2.x开发管理系统的时候提到了el-table手动拖动排序的需求,所以使用到了sortablejs,在开发过程中出现了Sortable: `el` must be an HTMLElement, not [object Null]的报错,记录一下我的解决方法:
因为项目需求是点击新增按钮弹出el-drawer的页面,然后在其里面的table中做拖动操作
弹出层:红框中为需要拖动的列表
但是我给对应table绑定方法时 el-drawer还未弹出也就是无法使用querySelector找到对应的table位置所以才会报这个错误
// 行拖拽
rowDrop() {
const tbody = document.querySelector(".caseAdd .el-table__body-wrapper tbody");
const _this = this;
Sortable.create(tbody, {
// 指定父元素下可被拖拽的子元素
draggable: ".el-table__row",
onEnd({ newIndex, oldIndex }) {
console.log(newIndex++ + "------------" + oldIndex++);
},
});
},
解决方案为当点击新增按钮后再调用此方法绑定拖动事件,但是又有一个bug,因为弹出过程有一段动画,所以得加上延时不然还是找不到对应的元素,不过该方法也有问题,如果页面刷新效率慢的话也会出现卡顿的问题,所以建议使用this.$nextTick,在界面元素更新完毕后执行
addOpen() {
this.drawerOpen = true;
let that=this;
//let tout=setTimeout(function(){
// that.rowDrop();
//},500)
this.$nextTick(() => {
that.rowDrop();
})
},
弹出层中的table结构:
<div class="draright">
<el-table :data="list" border height="85vh">
<el-table-column
prop="id"
width="80"
label="样机ID"
></el-table-column>
<el-table-column prop="jobCaseList" label="JobCase列表">
<template slot-scope="scopejob">
<el-table :data="scopejob.row.jobCaseList" border>
<el-table-column prop="jobId" width="55" label="ID">
</el-table-column>
<el-table-column prop="jobTitle" label="Job名称" width="200">
</el-table-column>
<el-table-column prop="CaseList" label="Case列表">
<template slot-scope="scopeCase">
<!--caseTable-->
<div class="caseAdd">
<el-table
:data="scopeCase.row.CaseList"
border
max-height="200"
<!--记得绑定row-key-->
row-key="caseId"
>
<el-table-column
prop="caseId"
label="ID"
width="55"
></el-table-column>
<el-table-column
prop="caseTitle"
label="名称"
></el-table-column>
<el-table-column label="操作" width="95">
<template slot-scope="ppop">
<el-button
slot="reference"
@click="getCode(ppop.row.id)"
>编辑</el-button
>
</template>
</el-table-column>
</el-table>
</div>
</template>
</el-table-column>
</el-table>
</template>
</el-table-column>
</el-table>
</div>
如果是很多个单独的列表要给每个循环添加拖动操作的话可以用这种方式动态添加class名称:
<!-- 动态添加class -->
<div :class="['caseAdd' + `${scopeCase.$index}`]">
<el-table
:data="scopeCase.row.CaseList"
border
max-height="200"
row-key="caseId"
style="cursor: move"
>
script:
//打开窗体时
addOpen() {
this.drawerOpen = true;
this.addRowDrop();
},
//添加事件
addRowDrop() {
let that = this;
//有多少个table就调用多少次方法
for(let i=0;i<this.list[0].jobCaseList.length;i++){
let tout = setTimeout(function () {
that.rowDrop(".caseAdd"+i+" .el-table__body-wrapper tbody");
}, 500);
}
},
// 行拖拽
rowDrop(docSelect) {
const tbody = document.querySelector(docSelect);
const _this = this;
Sortable.create(tbody, {
// 指定父元素下可被拖拽的子元素
draggable: ".el-table__row",
onEnd(evt) {
let caseID =
evt.path[0].rows[evt.newIndex].firstChild.firstChild.innerText;
let jboID = evt.path[7].cells[0].firstChild.innerText;
let cameraID = evt.path[14].cells[0].firstChild.innerText;
let index = 0;
let up = 0;
let down = 0;
//上下拖动时获取他上面或者下面的元素下标值
if (evt.newIndex > evt.oldIndex) {
index = evt.newIndex;
index--;
up = 0;
let ProCaseID =
evt.path[0].rows[index].firstChild.firstChild.innerText;
down = _this.getRealID(jboID, ProCaseID);
let RealId = _this.getRealID(jboID, caseID);
_this.setUD(cameraID, jboID, RealId, up, down);
} else if (evt.newIndex == evt.oldIndex) {
} else {
index = evt.newIndex;
index++;
let ProCaseID =
evt.path[0].rows[index].firstChild.firstChild.innerText;
down = 0;
up = _this.getRealID(jboID, ProCaseID);
let RealId = _this.getRealID(jboID, caseID);
_this.setUD(cameraID, jboID, RealId, up, down);
}
},
});
},
getRealID(jobID, caseID) {
let ids = 0;
for (let i = 0; i < this.list.length; i++) {
for (let j = 0; j < this.list[i].jobCaseList.length; j++) {
for (
let k = 0;
k < this.list[i].jobCaseList[j].CaseList.length;
k++
) {
if (
this.list[i].jobCaseList[j].CaseList[k].caseId == caseID &&
this.list[i].jobCaseList[j].jobId == jobID
) {
ids = this.list[i].jobCaseList[j].CaseList[k].id;
}
}
}
}
return ids;
},
//我的数据格式为:
{id: 14
jobCaseList: Array(2)
0:
CaseList: Array(7)
jobId: 45
jobTitle: "测试色彩",
1:
CaseList: Array(5)
jobId: 45
jobTitle: "asdasd"
}