table组件+vue-draggable-resizable拖拉拽组件,实现列的顺序更改和列宽的调整 —— 基于vue2.0 + ant-dezign-vue

一、需求背景

需要在现有的表格里面实现以下两个功能,

1、表格的列的顺序更改

2、表格列宽的调整

用户操作后需要保存到接口,刷新或重新进入都要复现保存后的操作结果

二、功能详解

表格列宽的调整功能,可以在网上找到很多详细案例很好解决。

难点在于表格的列的顺序更改功能,在vue3.0和react里有一些ui组件可以直接满足这个功能,但是在vue2.0内还是需要自行改造的,

具体思路如下:

1、使用components功能,给table的columns增加拖拽时用到的方法,

kotlin 复制代码
 <a-table
    :bordered="true"
    :id="dragTableId"
    :columns="filterColumns"
    :data-source="data"
    :pagination="{
    pageSize: 20
    }"
    :scroll="{ y: scrollY, x: '100%' }"
    tableLayout="fixed"
    :components="components"
  />

this.components = {
  header: {
    cell: (h, props, children) => {
      return this.setDragCell(h, props, children, {
        isOnlyChangeWidth: false,
        isTableCanDrag: true,
        tableColumns: this.columns, // 全部内容
        filterColumns: this.filterColumns, // 筛选内容,当前展示的内容,需要根据表结构封装
        boxId: 'project-list', // 页面id
        tableId: this.dragTableId // 表的id
      })
    }
  }
}

2、点击表头文字时新增一个表头icon表示可以移动,

ini 复制代码
   removeDom () { // 清除表头icon
      const thDom = document.getElementById('thDom')
      if (thDom) {
        thDom.remove()
      }
      window.removeEventListener('mousemove', this.moveWhthMouseMethod, false)
    },
    createDom (col, boxId) { // 初始化表头icon
      const thDom = document.createElement('li')
      thDom.id = 'thDom'
      thDom.innerText = col.title || col.remarkTitle
      var box = document.getElementById(boxId)
      box.appendChild(thDom)
      window.addEventListener('mousemove', this.moveWhthMouseMethod, false)
    },
    moveWhthMouseMethod (ev) { // 创建表头鼠标跟随元素
      const thDom = document.getElementById('thDom')
      let addPageX = 0
      let addPageY = 0
      if (this.dragTableId === 'planTableId') {
        addPageX = -50
        addPageY = -30
      }
      thDom.style.left = (ev.pageX - 300 - addPageX) + 'px'
      thDom.style.top = (ev.pageY - 150 - addPageY) + 'px'
    },

3、在鼠标移动的时候计算当前移动的位置,在相应的位置增加蓝色的高亮,

4、鼠标放松的时候删除蓝色高亮、表头icon、移动表格原列,增加表格新的移动列,

ini 复制代码
    getTargetIndex (filterColumns, targetWidth, colIndex, colWidth) { // 监听当前的拖拽到列表的哪个下标,注意前拖和后拖的区别
      if (targetWidth === 0) return
      if (targetWidth > 0 && targetWidth < colWidth) return
      if (targetWidth < 0 && targetWidth > -30) return
      let lenWidth = 0
      let targetIndex = null
      if (targetWidth > 0) { // 向后拖
        for (let i = 0; i < filterColumns.length; i++) {
          if (i > colIndex) {
            lenWidth += filterColumns[i].width
            if (lenWidth > targetWidth - colWidth) {
              targetIndex = i
              return targetIndex // 往index右边放置
            }
          }
        }
      } else { // 向前拖 反向遍历
        for (let i = filterColumns.length - 1; i >= 0; i--) {
          if (i < colIndex) {
            lenWidth -= filterColumns[i].width
            if (lenWidth < targetWidth) {
              targetIndex = i
              return targetIndex // 往index左放置
            }
          }
        }
      }
    },
        removeHighLight (tableId) { // 清除蓝色高亮线
      const thList = document.getElementById(tableId).querySelectorAll('.thHighLight')
      if (thList.length < 1) return
      for (let i = 0; i < thList.length; i++) {
        thList[i].remove()
      }
    },
    createHighLight (tableId, targetIndex, direction) { // 创建蓝色高亮线
      const thList = document.getElementById(tableId).querySelectorAll('th')
      const thHighLight = document.createElement('span')
      thHighLight.classList.add('thHighLight', direction)
      thList[targetIndex].appendChild(thHighLight)
      const trList = document.getElementById(tableId).querySelector('.ant-table-tbody').querySelectorAll('tr')
      for (let i = 0; i < trList.length; i++) {
        const tdList = trList[i].querySelectorAll('td')
        const tdHighLight = thHighLight.cloneNode(true)
        tdList[targetIndex].style.position = 'relative'
        tdList[targetIndex].appendChild(tdHighLight)
      }
    },

5、把使用的方法返回到columns,

kotlin 复制代码
      const dragChangeColumn = {
        key: col.dataIndex + 1 || col.key + 1,
        class: ['table-draggable-change-column', col.changeColumnLeft ? 'change-column-left' : ''],
        attrs: {
          w: (col.width > (attrsWidth.length * 12)) ? attrsWidth.length * 12 : 20,
          x: 30,
          z: 1,
          axis: 'x',
          draggable: true,
          transform: 'none',
          resizable: false
        },
        draggable: true,
        resizable: false,
        on: {
          // 拖动时把isdrag参数设置为true
          dragging: (x) => {
            // 建立跟随元素
            if (!isOnlyChangeWidth) {
              this.disableSelection(tableId)
            }
            if (!isdom) {
              this.createDom(col, boxId)
              isdom = true
            }
            const targetWidth = targetBefore === 0 ? x : x - targetBefore // 本次移动的X值
            const targetIndex = this.getTargetIndex(filterColumns, targetWidth, colIndex, col.width) // 移动到的位置
            if ((targetIndex || String(targetIndex) === '0') && targetIndexBefore !== targetIndex) {
              this.removeHighLight(tableId)
              if (targetWidth > colIndex) {
                this.createHighLight(tableId, isCanSelect ? targetIndex + 1 : targetIndex, 'right')
              } else {
                this.createHighLight(tableId, isCanSelect ? targetIndex + 1 : targetIndex, 'left')
              }
              targetIndexBefore = targetIndex
            }
            if (targetWidth === 0 || (targetWidth > 0 && targetWidth < col.width) || (targetWidth < 0 && targetWidth > -30)) {
              this.removeHighLight(tableId)
              targetIndexBefore = null
            }
            isDrag = true
          },
          // 拖动结束后把isdrag参数设置为false
          dragstop: (x) => {
            isDrag = true
            this.removeDom() // 删除跟随元素
            this.removeHighLight(tableId)
            targetIndexBefore = null
            isdom = false
            // 获取当前元素将要移动到的位置
            const targetWidth = targetBefore === 0 ? x : x - targetBefore // 本次移动的X值
            const targetIndex = this.getTargetIndex(filterColumns, targetWidth, colIndex, col.width) // 移动到的位置
            if ((targetIndex || String(targetIndex) === '0')) {
              this.changeColumns(tableColumns, filterColumns, targetIndex, colIndex)
              targetBefore = x
            }
            // eslint-disable-next-line vue/no-async-in-computed-properties
            setTimeout(() => {
              isDrag = false
            }, 300)
            if (!isOnlyChangeWidth) {
              setTimeout(() => {
                this.ableSelection(tableId)
              }, 2000)
            }
          }
        }
      }
kotlin 复制代码
      // 渲染vue-draggable-resizable插件到column中去,即可实现拖拽
      const dragWidth = h('vue-draggable-resizable', { ...dragPropsWidth })
      const dragColumn = h('vue-draggable-resizable', { ...dragChangeColumn })
      return h('th', { ...restProps, class: 'resize-table-th' }, [...children, dragWidth,

6、初始化时,有历史保存数据就使用,如果没有历史保存数据就使用默认数据,

csharp 复制代码
  async mounted () {
    this.tableColumnsNew = await this.getColumns({
      tableId: this.dragTableId,
      initColumns: this.projectListInitColumns // 默认数据
    })
  }

7、调整后的Columns会渲染回页面上,并且在接口保存。

kotlin 复制代码
 changeColumnsWidths (tableColumns, filterColumns, colIndex, col) { // 列宽更换时的数据处理
      const oldIndex = tableColumns.findIndex(item => { // 获取tableColumns当前列的Index
        const k = item.dataIndex || item.key
        return k === filterColumns[colIndex].dataIndex
      })
      this.tableColumnsNew.splice(oldIndex, 1, col)
      this.setColumns(this.dragTableId, this.tableColumnsNew)
    },
  changeColumns (tableColumns, filterColumns, targetIndex, colIndex) { // 列顺序更换的数据处理
      const newIndex = tableColumns.findIndex(col => { // 获取tableColumns的目标Index
        const k = col.dataIndex || col.key
        return k === filterColumns[targetIndex].dataIndex
      })
      const oldIndex = tableColumns.findIndex(col => { // 获取tableColumns当前列的Index
        const k = col.dataIndex || col.key
        return k === filterColumns[colIndex].dataIndex
      })
      const tableColumnsNew = JSON.parse(JSON.stringify(tableColumns))
      const newColumn = filterColumns.splice(colIndex, 1)[0]
      if (targetIndex > colIndex) {
        tableColumnsNew.splice(newIndex + 1, 0, newColumn)
        tableColumnsNew.splice(oldIndex, 1)
      } else {
        tableColumnsNew.splice(oldIndex, 1)
        tableColumnsNew.splice(newIndex, 0, newColumn)
      }
      this.tableColumnsNew = JSON.parse(JSON.stringify(tableColumnsNew))
      this.setColumns(this.dragTableId, this.tableColumnsNew)
    },

三、完整代码

setTableDragMixin.js

kotlin 复制代码
import { getAction, postAction } from '@/api/api'
import debounce from 'lodash/debounce' // 防抖

export default {
  props: {
  },
  data () {
    this.setColumns = debounce(this.setColumns, 1000) // 表头数据保存时的防抖
    this.changeColumnsWidths = debounce(this.changeColumnsWidths, 200) // 列宽更换的防抖
    return {
      tableColumnsNew: [] // 更改后的Columns
    }
  },
  computed: {
    tableColumnsNewString () { // 协助监听tableColumnsNew是否有更改
      return JSON.stringify(this.tableColumnsNew)
    }
  },
  beforeDestroy () { // 在组件生命周期结束的时候销毁。
    window.removeEventListener('mousemove', this.moveWhthMouseMethod, false)
  },
  mounted () {
  },
  methods: {
    columnsCheckFilter () { // 筛选表头展示的尾列补全
      this.addLastCulumnWidth()
    },
    addLastCulumnWidth () { // 筛选表头展示的尾列补全,如果筛选表头后,表格宽度不够总表宽,就增加最后一列列宽来补全
      let allWidth = 0
      if (this.isTableCanSelect) {
        allWidth += 60
      }
      this.tableColumnsNew.map(item => {
        if (item.show && item.dataIndex) {
          allWidth += item.width
        }
      })
      const dragTableWidth = document.getElementById(this.dragTableId).offsetWidth
      const addWidth = (dragTableWidth - allWidth) - 2 // 增加的宽度
      if (addWidth > 0) {
        for (let i = this.tableColumnsNew.length - 1; i >= 0; i--) {
          if (this.tableColumnsNew[i].show && this.tableColumnsNew[i].width) {
            this.tableColumnsNew[i].width += addWidth
            this.setColumns(this.dragTableId, this.tableColumnsNew)
            return
          }
        }
      }
    },
    ableSelection (tableId) { // 列拖拽结束时页面允许被选中,选中表外其他的元素来取消表内自动选中的状态
      const element = document.getElementById(tableId)
      element.classList.remove('userUnSelect')
      if (this.$refs.focusClick) {
        this.$refs.focusClick.focus()
      }
    },
    disableSelection (tableId) { // 列拖拽时页面禁止被选中
      const element = document.getElementById(tableId)
      element.classList.add('userUnSelect')
    },
    setColumns (tableId, columns) { // 保存表头信息
      const columnDetails = JSON.stringify(columns)
      postAction('Windchill/ptc1/user/tableView/createOrUpdate', {
        userName: sessionStorage.getItem('username'),
        tableName: tableId,
        columnDetails: columnDetails
      }).then(res => {
        if (res.data.success) {
        } else {
          this.$toast({
            text: res.data.message,
            type: 'warning'
          })
        }
      })
    },
    getColumns (params) { // 获取表头
      const { tableId, initColumns } = params
      return getAction('Windchill/ptc1/user/tableView/selectByUserNameAndTableName', {
        userName: sessionStorage.getItem('username'),
        tableName: tableId
      }).then(res => {
        if (res.data.success) {
          if (res.data.result) {
            return JSON.parse(res.data.result.columnDetails) // zqtodo改回来
            // this.setColumns(tableId, initColumns)
            // return initColumns
          } else { // 未存过信息用初始化表头, 并保存表头
            // this.setColumns(tableId, initColumns)
            return initColumns
          }
        } else {
          this.$toast({
            text: res.data.message,
            type: 'warning'
          })
        }
      })
    },
    changeColumnsWidths (tableColumns, filterColumns, colIndex, col) { // 列宽更换时的数据处理
      const oldIndex = tableColumns.findIndex(item => { // 获取tableColumns当前列的Index
        const k = item.dataIndex || item.key
        return k === filterColumns[colIndex].dataIndex
      })
      this.tableColumnsNew.splice(oldIndex, 1, col)
      this.setColumns(this.dragTableId, this.tableColumnsNew)
    },
    changeColumns (tableColumns, filterColumns, targetIndex, colIndex) { // 列顺序更换的数据处理
      const newIndex = tableColumns.findIndex(col => { // 获取tableColumns的目标Index
        const k = col.dataIndex || col.key
        return k === filterColumns[targetIndex].dataIndex
      })
      const oldIndex = tableColumns.findIndex(col => { // 获取tableColumns当前列的Index
        const k = col.dataIndex || col.key
        return k === filterColumns[colIndex].dataIndex
      })
      const tableColumnsNew = JSON.parse(JSON.stringify(tableColumns))
      const newColumn = filterColumns.splice(colIndex, 1)[0]
      if (targetIndex > colIndex) {
        tableColumnsNew.splice(newIndex + 1, 0, newColumn)
        tableColumnsNew.splice(oldIndex, 1)
      } else {
        tableColumnsNew.splice(oldIndex, 1)
        tableColumnsNew.splice(newIndex, 0, newColumn)
      }
      this.tableColumnsNew = JSON.parse(JSON.stringify(tableColumnsNew))
      this.setColumns(this.dragTableId, this.tableColumnsNew)
    },
    removeHighLight (tableId) { // 清除蓝色高亮线
      const thList = document.getElementById(tableId).querySelectorAll('.thHighLight')
      if (thList.length < 1) return
      for (let i = 0; i < thList.length; i++) {
        thList[i].remove()
      }
    },
    createHighLight (tableId, targetIndex, direction) { // 创建蓝色高亮线
      const thList = document.getElementById(tableId).querySelectorAll('th')
      const thHighLight = document.createElement('span')
      thHighLight.classList.add('thHighLight', direction)
      thList[targetIndex].appendChild(thHighLight)
      const trList = document.getElementById(tableId).querySelector('.ant-table-tbody').querySelectorAll('tr')
      for (let i = 0; i < trList.length; i++) {
        const tdList = trList[i].querySelectorAll('td')
        const tdHighLight = thHighLight.cloneNode(true)
        tdList[targetIndex].style.position = 'relative'
        tdList[targetIndex].appendChild(tdHighLight)
      }
    },
    removeDom () { // 清除表头icon
      const thDom = document.getElementById('thDom')
      if (thDom) {
        thDom.remove()
      }
      window.removeEventListener('mousemove', this.moveWhthMouseMethod, false)
    },
    createDom (col, boxId) { // 初始化表头icon
      const thDom = document.createElement('li')
      thDom.id = 'thDom'
      thDom.innerText = col.title || col.remarkTitle
      var box = document.getElementById(boxId)
      box.appendChild(thDom)
      window.addEventListener('mousemove', this.moveWhthMouseMethod, false)
    },
    moveWhthMouseMethod (ev) { // 创建表头鼠标跟随元素
      const thDom = document.getElementById('thDom')
      let addPageX = 0
      let addPageY = 0
      if (this.dragTableId === 'planTableId') {
        addPageX = -50
        addPageY = -30
      }
      thDom.style.left = (ev.pageX - 300 - addPageX) + 'px'
      thDom.style.top = (ev.pageY - 150 - addPageY) + 'px'
    },
    getTargetIndex (filterColumns, targetWidth, colIndex, colWidth) { // 监听当前的拖拽到列表的哪个下标,注意前拖和后拖的区别
      if (targetWidth === 0) return
      if (targetWidth > 0 && targetWidth < colWidth) return
      if (targetWidth < 0 && targetWidth > -30) return
      let lenWidth = 0
      let targetIndex = null
      if (targetWidth > 0) { // 向后拖
        for (let i = 0; i < filterColumns.length; i++) {
          if (i > colIndex) {
            lenWidth += filterColumns[i].width
            if (lenWidth > targetWidth - colWidth) {
              targetIndex = i
              return targetIndex // 往index右边放置
            }
          }
        }
      } else { // 向前拖 反向遍历
        for (let i = filterColumns.length - 1; i >= 0; i--) {
          if (i < colIndex) {
            lenWidth -= filterColumns[i].width
            if (lenWidth < targetWidth) {
              targetIndex = i
              return targetIndex // 往index左放置
            }
          }
        }
      }
    },
    setDragCell (h, props, children, params) { // 给table的columns增加拖拽时用到的方法,
      const { key, ...restProps } = props
      const { isTableCanDrag, tableColumns, filterColumns, boxId, tableId, isOnlyChangeWidth, isTableCanSelect } = params
      // 非必填 - isTableCanSelect: 是否可以勾选(表是否有前面那一排)
      // 必填 - isOnlyChangeWidth: 是否只允许改变列宽,不允许改变列排序
      // 必填 - isTableCanDrag: 是否允许允许改变列宽和改变列排序
      // 必填 - tableColumns: 全部列内容
      // 必填 - filterColumns: 展示列内容
      // 非必填 - boxId: 页面id
      // 必填 - tableId: 表格id
      if (!isTableCanDrag) { // 如果不添加功能就直接不给功能
        return h('th', { ...restProps }, [...children])
      }
      // 由于drag事件结束后必然会出发click事件,所以我们需要一个参数去判断当前操作是click点击事件还是drag拖拽事件
      let isDrag = false
      // 获取当前key值所对应的column信息
      const col = filterColumns.find(col => {
        const k = col.dataIndex || col.key
        return k === key
      })
      const colIndex = filterColumns.findIndex(col => {
        const k = col.dataIndex || col.key
        return k === key
      })
      // 如果col没有设置宽度,则直接原样渲染回去,不添加拉伸表格功能
      if (!col || !col.width) {
        return h('th', { ...restProps }, [...children])
      }
      // 如果存在宽度,则设置vue-draggable-resizable插件渲染参数,具体可以参考相关文档
      const dragPropsWidth = {
        key: col.dataIndex || col.key,
        class: (filterColumns.length - 2) === colIndex ? 'table-draggable-handle-last' : 'table-draggable-handle',
        attrs: {
          w: 10,
          x: col.width,
          z: 1,
          axis: 'x',
          draggable: true,
          transform: 'none',
          resizable: false
        },
        draggable: true,
        resizable: false,
        on: {
          // 拖动时把isdrag参数设置为true
          dragging: (x) => {
            isDrag = true
            col.width = Math.max(x, 50)
          },
          // 拖动结束后把isdrag参数设置为false
          dragstop: () => {
            isDrag = true
            // eslint-disable-next-line vue/no-async-in-computed-properties
            setTimeout(() => {
              isDrag = false
              this.changeColumnsWidths(tableColumns, filterColumns, colIndex, col)
            }, 300)
          }
        }
      }
      if (isOnlyChangeWidth) {
        const dragWidth = h('vue-draggable-resizable', { ...dragPropsWidth })
        return h('th', { ...restProps, class: 'resize-table-th' }, [...children, dragWidth])
      }
      let targetBefore = 0 // 当前x是否是上次的累加值
      let targetIndexBefore = null // 当前x是否是上次的累加值
      let isdom = false // 当前是否有跟随元素
      let isCanSelect = false // 我负责的,我创建的等列可选,前面多一行拉动时清除选中,改正高亮
      if (isTableCanSelect) {
        isCanSelect = true
      }
      const attrsWidth = col.title || col.remarkTitle
      const dragChangeColumn = {
        key: col.dataIndex + 1 || col.key + 1,
        class: ['table-draggable-change-column', col.changeColumnLeft ? 'change-column-left' : ''],
        attrs: {
          w: (col.width > (attrsWidth.length * 12)) ? attrsWidth.length * 12 : 20,
          x: 30,
          z: 1,
          axis: 'x',
          draggable: true,
          transform: 'none',
          resizable: false
        },
        draggable: true,
        resizable: false,
        on: {
          // 拖动时把isdrag参数设置为true
          dragging: (x) => {
            // 建立跟随元素
            if (!isOnlyChangeWidth) {
              this.disableSelection(tableId)
            }
            if (!isdom) {
              this.createDom(col, boxId)
              isdom = true
            }
            const targetWidth = targetBefore === 0 ? x : x - targetBefore // 本次移动的X值
            const targetIndex = this.getTargetIndex(filterColumns, targetWidth, colIndex, col.width) // 移动到的位置
            if ((targetIndex || String(targetIndex) === '0') && targetIndexBefore !== targetIndex) {
              this.removeHighLight(tableId)
              if (targetWidth > colIndex) {
                this.createHighLight(tableId, isCanSelect ? targetIndex + 1 : targetIndex, 'right')
              } else {
                this.createHighLight(tableId, isCanSelect ? targetIndex + 1 : targetIndex, 'left')
              }
              targetIndexBefore = targetIndex
            }
            if (targetWidth === 0 || (targetWidth > 0 && targetWidth < col.width) || (targetWidth < 0 && targetWidth > -30)) {
              this.removeHighLight(tableId)
              targetIndexBefore = null
            }
            isDrag = true
          },
          // 拖动结束后把isdrag参数设置为false
          dragstop: (x) => {
            isDrag = true
            this.removeDom() // 删除跟随元素
            this.removeHighLight(tableId)
            targetIndexBefore = null
            isdom = false
            // 获取当前元素将要移动到的位置
            const targetWidth = targetBefore === 0 ? x : x - targetBefore // 本次移动的X值
            const targetIndex = this.getTargetIndex(filterColumns, targetWidth, colIndex, col.width) // 移动到的位置
            if ((targetIndex || String(targetIndex) === '0')) {
              this.changeColumns(tableColumns, filterColumns, targetIndex, colIndex)
              targetBefore = x
            }
            // eslint-disable-next-line vue/no-async-in-computed-properties
            setTimeout(() => {
              isDrag = false
            }, 300)
            if (!isOnlyChangeWidth) {
              setTimeout(() => {
                this.ableSelection(tableId)
              }, 2000)
            }
          }
        }
      }
      // 取出column的click事件,对事件进行判断,如果现在isDrag参数为true,则截胡,防止拖动后触发click事件
      if (restProps.on && restProps.on.click) {
        const clickFunc = restProps.on.click
        restProps.on.click = (event) => {
          if (isDrag) {
            return
          }
          clickFunc(event)
        }
      }
      // 渲染vue-draggable-resizable插件到column中去,即可实现拖拽
      const dragWidth = h('vue-draggable-resizable', { ...dragPropsWidth })
      const dragColumn = h('vue-draggable-resizable', { ...dragChangeColumn })
      return h('th', { ...restProps, class: 'resize-table-th' }, [...children, dragWidth, dragColumn])
    }
  }
}

project-list.vue 引用方法文件

xml 复制代码
<template>
  <!-- id 一定要写-->
  <div class="project-list" id="project-list">
    <customFilter
    class="position-efined-customFilter" 
    :columns="columns" 
    :type="'projectList'" 
    @columnsCheckFilter="columnsCheckFilter"/>
   <!-- 增加components, id, :scroll-->
    <a-table
    :bordered="true"
    :id="dragTableId"
    :columns="filterColumns"
    :data-source="data"
    :pagination="{
    pageSize: 20
    }"
    :scroll="{ y: scrollY, x: '100%' }"
    tableLayout="fixed"
    :components="components"
    />
   </div>
</template>

<script>
import { projectListInitColumns } from './displayConfig/displayConfig'
import setTableDragMixin from '@/components/utils/setTableDragMixin.js'
const customFilter = () => import('@/components/display/custom-filter.vue')

export default {
  mixins: [setTableDragMixin],
  components: {
    customFilter
  },
   data () {
    this.components = {
      header: {
        cell: (h, props, children) => {
          return this.setDragCell(h, props, children, {
            isOnlyChangeWidth: false,
            isTableCanDrag: true,
            tableColumns: this.columns, // 全部内容
            filterColumns: this.filterColumns, // 筛选内容,当前展示的内容,需要根据表结构封装
            boxId: 'project-list', // 页面id
            tableId: this.dragTableId // 表的id
          })
        }
      }
    }
    return {
      // data需要增加show/dataIndex/width/最后的空title
      projectListInitColumns,
      dragTableId: 'project-list-table',
      columns: []
    }
  },
  computed: {
    filterColumns () {
      if (this.columns && this.columns.length > 0) {
        return this.columns.filter((col) => { if (col.show) { return col } })
      } else {
        return []
      }
    }
  },
  watch: {
     tableColumnsNewString: {
      deep: true,
      immediate: true,
      handler (val) {
        if (val && val.length > 2) {
          this.columns = this.tableColumnsNew
          // this.setColumns(this.dragTableId, this.columns)
          this.columns.forEach((item, index) => { // 如果需要合并列,要重新渲染, 该参数无法保存在接口
            if (!item.customCell && this.infoColumns[index].customCell) {
              item.customCell = (record) => this.defineUpdateCustomCell(record, item.dataIndex)
            }
            return item
          })
        }
      }
    }
  },
  async mounted () {
    this.tableColumnsNew = await this.getColumns({
      tableId: this.dragTableId,
      initColumns: this.projectListInitColumns
    })
    this.addLastCulumnWidth()
  }
</script>

四、优化建议

当前的表头存储的是全部数据。因此在读取表头数据时,如果表头中使用了某些方法,需要在监听里面重新赋值方法才能成功调用,由于这个设计,每次在更改表头默认信息时,都需要后端手动清除历史保存数据。在对比了Choerodon UI 的拖拉拽组件以后,建议在使用这组方法时,把当前的数据改造为只存储表头的id, 列宽,列顺序的存储格式,同时加上对应的通用读取数据的方法,能够更好的使用功能和维护数据。

相关推荐
GIS开发特训营7 分钟前
Vue零基础教程|从前端框架到GIS开发系列课程(七)响应式系统介绍
前端·vue.js·前端框架·gis开发·webgis·三维gis
Cachel wood33 分钟前
python round四舍五入和decimal库精确四舍五入
java·linux·前端·数据库·vue.js·python·前端框架
一个处女座的程序猿O(∩_∩)O3 小时前
小型 Vue 项目,该不该用 Pinia 、Vuex呢?
前端·javascript·vue.js
燃先生._.10 小时前
Day-03 Vue(生命周期、生命周期钩子八个函数、工程化开发和脚手架、组件化开发、根组件、局部注册和全局注册的步骤)
前端·javascript·vue.js
2401_8576009513 小时前
SSM 与 Vue 共筑电脑测评系统:精准洞察电脑世界
前端·javascript·vue.js
2401_8576009513 小时前
数字时代的医疗挂号变革:SSM+Vue 系统设计与实现之道
前端·javascript·vue.js
GDAL13 小时前
vue入门教程:组件透传 Attributes
前端·javascript·vue.js
轻口味13 小时前
Vue.js 核心概念:模板、指令、数据绑定
vue.js
2402_8575834913 小时前
基于 SSM 框架的 Vue 电脑测评系统:照亮电脑品质之路
前端·javascript·vue.js
java_heartLake14 小时前
Vue3之性能优化
javascript·vue.js·性能优化