ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

令人头秃的树形表格自由拖拽实现(vue+ant+Sortable)

2021-10-26 13:35:13  阅读:341  来源: 互联网

标签:index vue Sortable name targetItem id ant item children


最近项目提出目标,须实现树状表格自由拖拽,并可支持antdesign(elementui)一类ui框架表格部分功能,紧张的项目周期让人心情久久难以平复,这是连百度的回答都难以让我释怀的痛。没法自己撸呗,代码核心难点在于拖拽后需同步数据结构及同步表格视图。献祭无数根头发后,终成目标。实现效果如下(额外功能可根据antdesign配置属性自行添加):

代码如下 :

<template>
  <div>
    <a-table
      v-if="tableShow"
      :columns="columns"
      :data-source="dataList"
      :pagination="false"
      @expandedRowsChange="expandedTable"
      :expandedRowKeys="expandKeysList"
      rowKey="id"
    >
    </a-table>
  </div>
</template>
<script>
import Sortable from 'sortablejs'
export default {
  name: 'commonTable',
  data () {
    return {
      tableShow: true,
      columns: [
        {
          title: 'Name',
          dataIndex: 'name',
          key: 'name',
          scopedSlots: { customRender: 'name' }
        },
        {
          title: 'Age',
          dataIndex: 'age',
          key: 'age',
          width: '12%',
          scopedSlots: { customRender: 'age' }
        },
        {
          title: 'Address',
          dataIndex: 'address',
          width: '30%',
          key: 'address',
          scopedSlots: { customRender: 'address' }
        }
      ],
      dataList: [
        {
          key: 1313123,
          id: 1,
          name: '1',
          age: 60,
          address: 'New York No. 1 Lake Park',
          children: [
            {
              key: 11,
              name: '2',
              age: 42,
              address: 'New York No. 2 Lake Park',
              parentId: '1',
              id: '11'
            },
            {
              key: 12,
              name: '3',
              age: 30,
              address: 'New York No. 3 Lake Park',
              parentId: '1',
              id: '12',
              children: [
                {
                  key: 121,
                  id: '121',
                  name: '4',
                  age: 16,
                  address: 'New York No. 3 Lake Park',
                  parentId: '12'
                }
              ],
            },
            {
              key: 13,
              id: '13',
              parentId: '1',
              name: '5',
              age: 72,
              address: 'London No. 1 Lake Park',
              children: [
                {
                  key: 131,
                  parentId: '13',
                  id: '131',
                  name: '6',
                  age: 42,
                  address: 'London No. 2 Lake Park',
                  children: [
                    {
                      parentId: '131',
                      id: '1311',
                      key: 1311,
                      name: '7',
                      age: 25,
                      address: 'London No. 3 Lake Park',
                    },
                    {
                      parentId: '131',
                      id: '1312',
                      key: 1312,
                      name: '8',
                      age: 18,
                      address: 'London No. 4 Lake Park',
                    },
                  ],
                },
              ],
            },
          ],
        },
        {
          key: 2,
          id: '2',
          name: '9',
          age: 32,
          address: 'Sidney No. 1 Lake Park',
        }
      ],
      expandKeysList: []
    }
  },
  methods: {
    expandedTable (keys) {
      if (this.tableShow) {
        this.expandKeysList = keys
      }
      this.refreshTable()
    },
    inintDrag () {
      let sortDom = document.querySelector('.ant-table-tbody')
      let _this = this
      Sortable.create(sortDom, {
        onStart ({ item }) {
          let targetRowKey = item.dataset.rowKey
          if (targetRowKey) {
            _this.expandKeysList = _this.expandKeysList.filter(item => item.toString() !== targetRowKey.toString())
          }
        },
        onEnd ({ newIndex, item }) {
          let targetRowKey = item.dataset.rowKey
          let targetArray = []
          let dataListItem = {}
          let targetItem = {}
          if (targetRowKey) {
            targetArray = _this.getTargeIndex(_this.dataList, targetRowKey.toString())
          }
          targetArray.forEach((item, index) => {
            item = parseInt(item)
            if (index < targetArray.length - 1) {
              if (!index) {
                targetItem = _this.dataList[item]
              } else {
                targetItem = targetItem.children[item]
              }
            } else {
              if (!index) {
                targetItem = JSON.stringify(_this.dataList[item])
                _this.dataList.splice(item, 1)

              } else {
                let calcItem = JSON.stringify(targetItem.children[item])
                targetItem.children.splice(item, 1)
                if (!targetItem.children.length) {
                  delete targetItem.children
                }
                targetItem = calcItem
              }
            }
          })
          if (newIndex > 0) {
            let isNext = false
            let currentRowKey = document.querySelectorAll('.ant-table-row')[newIndex - 1].dataset.rowKey
            if (document.querySelectorAll('.ant-table-row')[newIndex + 1]) {
              currentRowKey = document.querySelectorAll('.ant-table-row')[newIndex + 1].dataset.rowKey
              isNext = true
            }
            let currentArray = []
            if (currentRowKey) {
              currentArray = _this.getTargeIndex(_this.dataList, currentRowKey.toString())
            }
            currentArray.forEach((item, index) => {
              item = parseInt(item)
              if (index < currentArray.length - 1) {
                if (!index) {
                  dataListItem = _this.dataList[item]
                } else {
                  dataListItem = dataListItem.children[item]
                }
              } else {
                if (!index) {
                  if (!isNext) {
                    _this.dataList.splice(item + 1, 0 , JSON.parse(targetItem))
                  } else {
                    _this.dataList.splice(item, 0 , JSON.parse(targetItem))
                  }
                } else {
                  if (!isNext) {
                    dataListItem.children.splice(item + 1, 0, JSON.parse(targetItem))
                  } else {
                    dataListItem.children.splice(item, 0, JSON.parse(targetItem))
                  }
                }
              }
            })
          } else {
            _this.dataList.unshift(JSON.parse(targetItem))
          }
          _this.dataList = JSON.parse(JSON.stringify(_this.dataList))
          _this.refreshTable()
        }
      })
    },
    getTargeIndex (list, id, arr = []) {
      return list.reduce((total, item, index) => {
        if (item.id.toString() === id) {
          return [...total, index]
        } else {
          if (item.children && item.children.length) {
            let childArr = this.getTargeIndex(item.children, id, [...arr, index])
            if (childArr.length === [...arr, index].length) {
              childArr = total
            }
            return childArr
          } else {
            return total
          }
        }
      }, arr)
    },
    refreshTable () {
      this.tableShow = false
      this.$nextTick(() => {
        this.tableShow = true
        this.$nextTick(() => {
          this.inintDrag()
        })
      })
    }
  },
  mounted () {
    this.inintDrag()
  }
}
</script>

标签:index,vue,Sortable,name,targetItem,id,ant,item,children
来源: https://blog.csdn.net/weixin_43951323/article/details/120970155

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有