sortable.js el-table 树形表 拖拽

image

实现的功能:

  1. 该树形表只有一级子节点
  2. 该子节点只能在当前父节点中拖拽, 不能跨父节点拖拽
  3. 同时只能展开一个父节点, 其他父节点闭合

实现的关键点:

  1. mounted 挂载 初始化sortable
  2. 拖拽完onEnd方法返回的index扁平化数组的排序
    调用该方法getTable()
  3. 后台多返回一个kid,和id的值一样,
<el-table row-key="kid"/>
  1. 如果拖拽的是父节点,父节点和子节点中的kid重新生成,让el-table局部刷新,不然会出现父节点移除,子节点还是在原有的位置,但是tableData中已经是最新的数据
  2. 拖拽完成之后调用接口保存当前排序
    如果拖拽父节点,只传父节点kid, 从convertMap对象找对应的index
    如果拖拽子节点,传子节点kid,从convertMapChild对象找对应的index
    image
    image
//树形数组扁平化
    getTable(data) {
      data.forEach(d => {
        const obj = {
          ...d,
          cid: [],
        }
        delete obj.children
        this.tempData.push(obj)
        if (d.children && d.children.length > 0) {
          d.children.forEach(c => {
            obj.cid.push(c.id)
          })
          this.getTable(d.children)
        }
      })
    },

mounted时调用的方法

rowDrop() {
      const tb = document.querySelector('tbody')
      Sortable.create(tb, {
        handle: '.drop', 
        animation: 180,
        delay: 0,
        onEnd: ({ newIndex, oldIndex }) => {
          this.idIndexMap()
          this.newIndex = newIndex
          this.oldIndex = oldIndex
          this.tempData = []
          this.getTable(this.tableData)
          const newData = this.tempData.at(newIndex)
          const delData = this.tempData.at(oldIndex)
          //第一层级移动,删除拖拽节点,包括拖拽节点的子节点,更新convertMap,id对应的索引
          if (delData.cid && delData.cid.length > 0 || delData.parentId === 0) {
            const delTdIndex = this.convertMap[delData.id]
            const newTdIndex = this.convertMap[newData.id]
            const [dd] = this.tableData.splice(delTdIndex, 1)

            dd.kid = this.getUuid()

            dd.children.map(d => {
              d.kid = this.getUuid()
              return d
            })

            this.tableData.splice(newTdIndex, 0, dd)
            this.idIndexMap()
          } else if (newData.parentId === delData.parentId) {
            //子层级移动 重新生成convertMapChild,更新id对应的索引
            const parentIndex = this.convertMap[newData.parentId]
            const parentData = this.tableData[parentIndex]
            const children = parentData.children
            this.generateIdToIndexChild(children)
            children.splice(this.convertMapChild[delData.id], 1)
            children.splice(this.convertMapChild[newData.id], 0, delData)
            this.generateIdToIndexChild(children)
          }
        },
        //选择的时候记住拖拽节点的索引
        onChoose: ({ oldIndex }) => {
          this.oldIndex = oldIndex
        },
        onMove: (customEvent, dragEvent) => {
        //移动到新节点会有新节点的索引,和拖拽节点的父id进行
       //比较,如果不一致,不让拖拽,返回false
          this.tempData = []
          this.getTable(this.tableData)
          this.newIndex = customEvent.related.rowIndex
          const newData = this.tempData.at(this.newIndex)
          const delData = this.tempData.at(this.oldIndex)
          if (newData.parentId !== delData.parentId) {
            return false
          }
        }
      })
    },

拖拽一级节点先转化为 id--index的对应关系

    idIndexMap() {
      this.convertMap = this.tableData.reduce((acc, cur, index) => {
        return {
          ...acc,
          [cur.id] : index
        }
      }, {})
    },

拖拽子节点生成Map id--index的对应关系

    generateIdToIndexChild(children) {
      console.log(children);
      this.convertMapChild = children.reduce((acc, cur, index) => {
        return {
          ...acc,
          [cur.id] : index
        }
      }, {})
    },
posted @   躺尸的大笨鸟  阅读(1942)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具
点击右上角即可分享
微信分享提示