elTable实现树形结构拖拽功能

问题描述:当一个表格,有很多层嵌套数据时,想实现拖拽改变顺序

使用方法:sortablejs

第一步:安装sortablejs

npm install sortablejs --save

第二步:在需要的地方引入  

import Sortable from 'sortablejs'

第三步:准备需要的表格

<template>
  <div>
    <el-table ref="dragTable" row-key="id" :data="treeTableData" :expand-row-keys="treeTableExpandKeys" border @expand-change="treeTableExpandChange">
      <el-table-column prop="name" label="名字"></el-table-column>
      <el-table-column prop="age" label="年龄"></el-table-column>
      <el-table-column prop="desc" label="描述"></el-table-column>
    </el-table>
</div>
</template>

第四步:data定义数据

 data() {
    return {
      treeTableData: [
        {
          id: '1',
          name: '张三',
          age: 11,
          desc: '法外狂徒',
          children: [
            {
              id: '2',
              name: '月尊大人',
              age: 15,
              desc: '小兰花',
              children: [
                {
                  id: '6',
                  name: '仓盐海',
                  age: 15,
                  desc: '云梦泽'
                }
              ]
            }
          ]
        },
        {
          id: '3',
          name: '凌不疑',
          age: 18,
          desc: '三三',
          children: [
            {
              id: '4',
              name: '四四',
              age: 25,
              desc: '五五'
            },
            {
              id: '5',
              name: '不知道叫什么了',
              age: 26,
              desc: '哈哈哈'
            }
          ]
        }
      ],
      flatTreeData: [],
      treeTableExpandKeys: [],
      sortableObj: null
}
}

初始化

mounted(){
   this.transverseNode(this.treeTableData, 1, (node, level, parentNode) => {
      node.level = level
      node.parentId = parentNode ? parentNode.id : -1
    })
   his.initSortable()
   this.getFlatNode(this.treeTableData, this.flatTreeData)
}

方法

​
beforeDestroy() {
    if (this.sortableObj) {
      this.sortableObj.destroy()
    }
  },
 methods: {
    initSortable() {
      // 获取容器元素
      const el = this.$refs.dragTable.$el.querySelectorAll('.el-table__body-wrapper > table > tbody')[0]

      if (!el) return

      this.sortableObj = new Sortable(el, {
        group: 'dragName',
        draggable: '.el-table__row',
        onEnd: evt => {
          const { newIndex, oldIndex } = evt
          const dragRow = this.flatTreeData[oldIndex]
          const relatedRow = this.flatTreeData[newIndex]
          if (dragRow.parentId !== relatedRow.parentId) {
            this.$message.warning('只能同层级内排序')
            this.reRender(null, 'treeTableData')
          } else {
            // 都无children
            if (!dragRow.children && !relatedRow.children) {
              const oldData = this.flatTreeData.splice(oldIndex, 1)[0]
              this.flatTreeData.splice(newIndex, 0, oldData)
            }

            // drag有, relate无
            if (dragRow.children && !relatedRow.children) {
              const oldData = this.flatTreeData.splice(oldIndex, 1)[0]
              this.flatTreeData.splice(newIndex, 0, oldData)

              if (newIndex < oldIndex) {
                // 有子元素的,子元素需要同样跟上来
                const flatChildren = []

                this.getFlatNode(oldData.children || [], flatChildren)
                if (flatChildren.length > 0) {
                  for (let i = 1, len = flatChildren.length; i <= len; i++) {
                    const childData = this.flatTreeData.splice(oldIndex + i, 1)[0]
                    this.flatTreeData.splice(newIndex + i, 0, childData)
                  }
                }
              } else {
                // 有子元素的,子元素需要同样跟下来
                const flatChildren = []

                this.getFlatNode(oldData.children || [], flatChildren)
                if (flatChildren.length > 0) {
                  for (let i = 1, len = flatChildren.length; i <= len; i++) {
                    const childData = this.flatTreeData.splice(oldIndex, 1)[0]
                    this.flatTreeData.splice(newIndex, 0, childData)
                  }
                }
              }
            }

            // drag无, relate有
            if (!dragRow.children && relatedRow.children) {
              const oldData = this.flatTreeData.splice(oldIndex, 1)[0]
              this.flatTreeData.splice(newIndex, 0, oldData)

              if (newIndex > oldIndex) {
                // 有子元素的,子元素需要同样跟上来
                const flatChildren = []

                this.getFlatNode(relatedRow.children || [], flatChildren)
                if (flatChildren.length > 0) {
                  for (let i = 1, len = flatChildren.length; i <= len; i++) {
                    const childData = this.flatTreeData.splice(newIndex + i, 1)[0]
                    this.flatTreeData.splice(newIndex + i - 1, 0, childData)
                  }
                }
              }
            }

            // drag有, relate有
            if (dragRow.children && relatedRow.children) {
              if (newIndex < oldIndex) {
                const oldData = this.flatTreeData.splice(oldIndex, 1)[0]
                this.flatTreeData.splice(newIndex, 0, oldData)

                // 有子元素的,子元素需要同样跟上来
                const flatChildren = []

                this.getFlatNode(oldData.children || [], flatChildren)
                if (flatChildren.length > 0) {
                  for (let i = 1, len = flatChildren.length; i <= len; i++) {
                    const childData = this.flatTreeData.splice(oldIndex + i, 1)[0]
                    this.flatTreeData.splice(newIndex + i, 0, childData)
                  }
                }
              } else {
                const oldData = this.flatTreeData.splice(oldIndex, 1)[0]

                // relateRow的children数
                const relateFlatChildren = []
                this.getFlatNode(relatedRow.children || [], relateFlatChildren)

                this.flatTreeData.splice(newIndex + relateFlatChildren.length, 0, oldData)

                // 有子元素的,子元素需要同样跟下来
                const flatChildren = []

                this.getFlatNode(oldData.children || [], flatChildren)
                if (flatChildren.length > 0) {
                  for (let i = 1, len = flatChildren.length; i <= len; i++) {
                    const childData = this.flatTreeData.splice(oldIndex, 1)[0]
                    this.flatTreeData.splice(newIndex + relateFlatChildren.length, 0, childData)
                  }
                }
              }
            }

            // 重新生成树的数据
            const data = this.getTreeData(this.flatTreeData, [])
            console.log('this.flatTreeData', this.flatTreeData, data)
            // 页面重新渲染
            this.reRender(data, 'treeTableData')
          }
        }
      })
    },
    getFlatNode(nodes, flatList, childrenKey = 'children') {
      nodes.forEach(node => {
        flatList.push(node)
        if (node[childrenKey] && node[childrenKey].length) {
          this.getFlatNode(node[childrenKey], flatList)
        }
      })
    },
    getTreeData(nodes, resultList) {
      const childStack = []
      let lastNode = {}
      nodes.forEach(node => {
        delete node.children

        const pushNode = dataNode => {
          const parentNode = childStack[childStack.length - 1]
          if (parentNode) {
            parentNode.children.push(dataNode)
          } else {
            resultList.push(dataNode)
          }
        }

        if (node.level < lastNode.level) {
          childStack.length = node.level - 1
          pushNode(node)
        } else if (node.level === lastNode.level) {
          pushNode(node)
        } else if (node.level > lastNode.level) {
          if (!lastNode.children) {
            lastNode.children = []
          }
          childStack.push(lastNode)
          pushNode(node)
        } else {
          resultList.push(node)
        }

        lastNode = node
      })

      return resultList
    },
    reRender(data, dataKey) {
      if (data) {
        this[dataKey] = []
        this.$nextTick(() => {
          this[dataKey] = data
        })
      } else {
        const origin = [].concat(this[dataKey])
        this[dataKey] = []
        this.$nextTick(() => {
          this[dataKey] = origin
        })
      }
    },
    transverseNode(nodes, level = 1, cb, parentNode, childKey = 'children') {
      nodes.forEach(node => {
        if (node[childKey] && node[childKey].length > 0) {
          this.transverseNode(node[childKey], level + 1, cb, node, childKey)
        }
        cb(node, level, parentNode)
      })
      return nodes
    },
    treeTableExpandChange(row, expanded) {
      if (expanded) {
        this.treeTableExpandKeys.push(row.id)
      } else {
        const idx = this.treeTableExpandKeys.indexOf(row.id)
        this.treeTableExpandKeys.splice(idx, 1)
      }
    }
  }
​

  • 7
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值