引入sortablejs插件实现表格列拖拽功能的封装

1 参考其他文章

Vue+ElementUI 实现 动态调整表格列 显示隐藏&显示顺序

2 具体实现

2.1 将列拖拽功能封装到通用表格动态列组件里

关于表格动态列组件的具体代码,可以看我的另一篇博客:Vue - 基于Element UI封装一个表格动态列组件。

2.2 实现思路
  1. 引入sortablejs插件;
  2. 获取显示的表格列数据;
  3. 考虑动态列之前的列,如下图,Sortable获取的index是对应整个表格的列数据index,动态列数据需要减去emty;
    引入sortablejs插件实现表格列拖拽功能的封装_第1张图片
  4. 获取原来位置下标和新位置下标(考虑动态列表包含visible为false数据,作查找位置(findIndex)后找到其index下标);
  5. 删除原来位置列数据、在新位置插入该列数据;
  6. 使用时需要获取表格Dom元素,当一个页面有多个表格的情况,需要加一个类去获取到对应的表格Dom元素,故传入tableSign变量。

2.3 列拖拽具体代码

import Sortable from 'sortablejs'
export default {
	props: {
	    // 非必传,只有存在多个表格时,该参数作为表格的唯一标识,主要用于拖拽
	    tableSign: {
	      type: String,
	      default: null
	    },
	    // 所有的列字段,用于拖拽
	    schemas: {
	      type: Array,
	      default: () => {
	        return []
	      }
	    },
	    // 不在schemas内,并且在动态列之前的列数
	    empty: {
	      type: Number,
	      default: 0
	    },
    },
	mounted() {
	   // 表格拖拽方法
	   if (this.schemas.length > 0) {
	     this.columnDrop()
	   }
	},
	
	methods: {
		 /**
		  * 列拖拽
		  */
		 columnDrop() {
		   // 页面多个表格 取到对应表格dom元素
		   let wrapperClass = '.el-table__header-wrapper'
		   if (this.tableSign) {
		     const elClass = this.$parent.$el.getAttribute('class')
		     if (!elClass.includes(this.tableSign)) {
		       this.$parent.$el.setAttribute('class', `${elClass} ${this.tableSign}`)
		     }
		     wrapperClass = `.${this.tableSign} ${wrapperClass}`
		   }
		   const wrapperTr = document.querySelector(`${wrapperClass} tr`)
		
		   this.sortable = Sortable.create(wrapperTr, {
		     animation: 100, // 过渡动画
		     delay: 0, // 延迟多久可以拖动
		     onEnd: (evt) => {
		       if (evt.oldIndex === evt.newIndex) return
		
		       const overviewColumns = [...this.schemas]
		       const visbleColumns = overviewColumns.filter((v) => v.visible) // 显示的列
		       const empty = this.empty // 不在schemas内,并且在动态列之前的列数
		
		       // 注意:动态列表包含visible为false数据,需要进行特殊查找位置处理
		       const oldItem = visbleColumns[evt.oldIndex - empty]
		       const newItem = visbleColumns[evt.newIndex - empty]
		
		       const realOldIndex = overviewColumns.findIndex(
		         (item) => item.prop === oldItem.prop
		       )
		       const realNewIndex = overviewColumns.findIndex(
		         (item) => item.prop === newItem.prop
		       )
		       overviewColumns.splice(realOldIndex, 1) // 删除原来位置的数据
		       overviewColumns.splice(realNewIndex, 0, oldItem) // 在新的位置插入该数据
		
		       this.$emit('changeColumn', overviewColumns)
		     }
		   })
		 }
	}
}

2.4 在页面中使用

        <el-table
          ref="allListTableRef"
          v-loading="tableLoading"
          size="mini"
          :data="infoList"
          height="430px"
          :cell-style="cellStyle"
          @sort-change="handleSortChange"
          @selection-change="handleSelectionChange"
        >
          <el-table-column type="selection" width="55" align="center" />

          <DynamicColumn
            v-for="(ite, index) in overviewColumns"
            :key="index"
            :item="ite"
            :empty="1"
            :data-list="infoList"
            table-sign="all-list"
            :schemas="overviewColumns"
            @changeColumn="(cols)=>{overviewColumns=cols;}"
          />

          <el-table-column
            :label="$t('operate')"
            prop="operate"
            align="center"
            width="200"
            fixed="right"
          >
            <template slot-scope="scope">
              <el-button
                v-hasPermi="['investmentDecision:etfPool:etfList:index:detail']"
                type="text"
                size="mini"
                icon="el-icon-info"
                @click="goDetail(scope.row)"
              >{{ $t("viewDetails") }}</el-button>
            </template>
          </el-table-column>
        </el-table>

      // 动态列
      overviewColumns: this.$columns.getColumns('etfPool_list_overview'),
      // 表格数据
      infoList: [],

你可能感兴趣的:(vue,前端,vue.js,前端)