el-table树形列表拖拽排序(sortablejs)

思路:
首先el-table上面row-class-name绑定要传的id,
然后将树形结构的数据转换成平铺的列表结构,

拖拽结束后的监听事件onEnd内可以获取到
通过拖拽可以获取到 旧数据 与 新数据对象以及拖拽后平铺的数据顺序,
这时可以通过拖拽后平铺的数据顺序配合parentId来知道当前层级的顺序和id
将这排好顺序的id数组传给后端,后端返回最新的数据

拖拽中事件监听onMove内可以阻止树形结构内的子集拖拽出去。

1.引入sortablejs

npm install sortablejs --save

2.组件中使用

import Sortable from 'sortablejs';
<el-table :data="menuList" row-key="menuId" :row-class-name="tableClassNmae" :expand-row-keys="expandRowKeys" v-if="showFlag"></el-table>
tableClassNmae(row){
   return 'id=' + row.row.id + ''
}

// 将树数据转化为平铺数据
function treeToTile(treeData, childKey = 'children') {
  const arr = []
  const expanded = data => {
    if (data && data.length > 0) {
      data.filter(d => d).forEach(e => {
        arr.push(e)
        expanded(e[childKey] || [])
      })
    }
  }
  expanded(treeData)
  return arr
}


let activeRows = reactive([]);
let flag = true;
let expandRowKeys=ref([]) //展开行的id,底下用的是拖拽行的parentId,其实就是应该展开的行
let showFlag=ref([true])
let menuList=ref([]) //表格数据
onmounted(()=>{
  //获取需要添加拖拽的组件
  const el = document.querySelector(".el-table__body-wrapper tbody");
  //设置拖拽的参数
  const ops = {
    animation: 200, //动画时长
    handle: ".el-table__row", //可拖拽区域class
    ghostClass: "ghost", //拖拽位置样式class
    dataIdAttr: "class", //配合row-class-name设置使用
    //拖拽中事件监听
    onMove: ({ dragged, related }) => {
      activeRows = treeToTile(props.tdata) // 把树形的结构转为列表再进行拖拽  
      const oldRow = activeRows[dragged.rowIndex] //旧位置数据
      const newRow = activeRows[related.rowIndex] //被拖拽的新数据
      if (oldRow.parentId !== newRow.parentId) {
        flag = false
      } else {
        flag = true
      }

      return flag
    }, 
   //拖拽后事件监听
    onEnd(evt) {
      activeRows = treeToTile(props.tdata) // 把树形的结构转为列表再进行拖拽  
      const oldRow = activeRows[evt.oldIndex] // 移动的那个元素
      var arr = sortable2.toArray(); //获取排序后的平铺数据顺序
      for (let index = 0; index < arr.length; index++) {
        arr[index] = arr[index].match(/(?<=\bid=)[\d]+/g)[0];
      }
      let aa = activeRows.filter(d => d.parentId != oldRow.parentId).map(d => d.id);
      let bb = (arr.filter(d => aa.indexOf(d) == -1))
    if (evt.oldIndex !== evt.newIndex) {
      if (flag) {
       //调用后台接口传出bb排好序的数组,让后端返回排好的数据,在请求成功的回调里执行如下操作
        showFlag.value=false;  //刷新拖拽后的结构
           nextTick(()=>{
           showFlag.value=true;   //刷新拖拽后的结构
           menuList.value=res.data;  //重新赋值
           expandRowKeys.value=[...e.parentId]  //拖拽后让原有的行展开
       }) 
           expandRowKeys=[...oldRow.parentId] //让选中行展示
       }
      }
    },
  };
  // //初始化拖拽表格
  var sortable2 = Sortable.create(el, ops);
})
  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
如果你使用的是 ElementUI 中的 el-table 树形表格,那么你可以通过设置 `treeProps` 属性来指定树形结构的相关属性。其中包括 `children` 表示子节点的属性名,`hasChildren` 表示是否有子节点的属性名。 在排序时,你可以使用 `sort` 属性来指定排序规则,例如: ```html <el-table :data="tableData" :tree-props="{ children: 'children', hasChildren: 'hasChildren' }" :sort-method="sortTable"> <el-table-column prop="name" label="名称" sortable></el-table-column> <el-table-column prop="age" label="年龄" sortable></el-table-column> </el-table> ``` 其中,`sort-method` 属性指定了排序方法,可以在 `methods` 中定义: ```js methods: { sortTable(a, b) { // 判断是否为根节点 const aParent = this.getParentNode(a) const bParent = this.getParentNode(b) const aIsRoot = !aParent const bIsRoot = !bParent // 根节点优先 if (aIsRoot && !bIsRoot) { return -1 } else if (!aIsRoot && bIsRoot) { return 1 } // 比较节点值 if (a[this.sortField] > b[this.sortField]) { return this.sortOrder === 'ascending' ? 1 : -1 } else if (a[this.sortField] < b[this.sortField]) { return this.sortOrder === 'ascending' ? -1 : 1 } else { return 0 } }, getParentNode(node) { // 获取当前节点的父节点 const parentKey = this.$refs.table.treeProps.children const parentNode = this.$refs.table.getNodeById(node[parentKey]) return parentNode } } ``` 在 `sortTable` 方法中,首先判断当前节点是否为根节点,如果是根节点则优先排在前面。然后再比较节点值进行排序。在获取父节点时,可以使用 `$refs` 获取到 el-table 的实例,然后调用 `getNodeById` 方法获取节点对应的行数据。 以上是一个示例代码,你可以根据自己的实际需求进行修改。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值