element-ui树形表格增加子级上移,下移功能
当时的需求
- 能够拖拽子级 进行排序
- 只能同级拖拽不能越级
vue 2.6
疑问
其实刚开始去网上找解决方案的时候, 有看到elemrnt-ui+sotable.js 得拖拽方案(双厨狂喜), 立马 npm install 进去操作,结果发现 其实对于业务来说 sortable 不符合要求 因为拖拽完成后的 onMove这个回调函数里 我要判断是否是 父级 或者说当它越级后 我要阻止这一次 拖拽 结果 当子项拖出 父级后 我返回 false 结果子项没有回复原位 而是放置到了 拖拽完成后的子项后面 因为时间也比较急所以 不想去探究原因 最后商量说是 在页面上增加上移下移按钮 进行排序 (详情可以看看这个链接)www.itxst.com/sortablejs/…
实际操作
增加按钮上移 下移功能要比拖拽好做一些, 可以点击获取数据, 流程大致 如下
Start
--> 点击获取id
--> 将树形数据扁平化
--> 然后找到这个id
--> 判断他是否是数组第一个还是最后一个(这两种情况不能上下移动)
--> 和上(下)一个子项交换位置
--> 然后数据变成树形结构 将数据表格得tablelist 重新赋值
--> Stop
这样做确实没问题 但是频繁将数据扁平化 然后又化成树形 感觉以后数据量一多肯定完蛋 (化成树形 一般来说几乎都是递归 所以正是不足所在)
解决方案
Start
-->页面初始化created() 的时候 递归一次全部树形数据
增加一个level 字段比方 根节点 1 根节点第一个就是 1.1 下面的节点就是依次用'.'分割
-->点击获取id
-->首先通过这个id 解析上面的level 比方1.1.1 通过换成[1,1,1]循环,
得出tree的位置的字符串(this.list[0].children[0].children[0]),
做判断是否是第一个或者最后一个是的话不允许上下移动
通过eval(str) 完成数组取值
-->通过两次this.$set 方法交换上移数据 和 目标数据的值 达成上移下移效果 最后保存提交给后台
$set 参数用eval取值出来就好
--> Stop
下面的方法就不需要重复的将原本树形数据扁平化, 在生成树形要好的多 我少了一次递归的方法
总结
其实普通流程可以在页面初始化的时候生成一个扁平化的数据 然后再走普通流程会少一点性能消耗, 但是还是会存在将数据变成树形的一个操作 还是没有直接查找树形数据来的方便。一次业务上的解决方案怕忘记所以记下来了, 可能还有更好的方法 希望大佬们不要喷我 能力只有这么高哈哈 但是也希望大佬们有更好的方案交流
贴一下自己的代码片段 可能只有自己看的懂 没做本地化处理啊
getTreeIndex (data) {
let str = `this.list[]`;
data.forEach((item, index, arr) => {
if (index == 0) {
str = `this.list[${arr[0] - 1}]`;
} else {
str = str + `.children[${arr[index] - 1}]`;
}
});
return str;
},
moveUpTree () {
//当前选中行
console.log("currentRow", this.currentRow);
if (this.currentRow.index == 1) {
//根节点
return;
}
if (!!this.currentRow.index) {
const { index } = this.currentRow;
console.log("currentRow", this.currentRow);
let indexarr = index.split(".");
if (indexarr[indexarr.length - 1] == "1") {
// 判断是否是同级第一个
this.$message("已是同级第一行无法上移");
} else {
let selectrow, tragetrow;
if (!!this.currentRow.index) {
selectrow = this.currentRow.index.split(".");
tragetrow = selectrow.slice(0);
tragetrow[tragetrow.length - 1] = (
parseInt(tragetrow[tragetrow.length - 1]) - 1
).toString();
}
let selectStr = this.getTreeIndex(selectrow); // 获取树节点路径 字符
let targetStr = this.getTreeIndex(tragetrow);
let selectChild = selectStr.substring(0, selectStr.lastIndexOf("[")); // 字符数组
let targetChild = targetStr.substring(0, targetStr.lastIndexOf("["));
console.log(eval(targetStr), eval(targetChild));
let obj = eval(selectStr);
this.$set(
eval(selectChild),
parseInt(selectrow[selectrow.length - 1]) - 1,
eval(targetStr)
);
this.$set(
eval(targetChild),
parseInt(tragetrow[tragetrow.length - 1]) - 1,
eval(obj)
);
this.setTableIndex(this.list);
}
} else {
this.$message("请选中一行");
}
},