elementUI实现动态拖拽表头、可拖拽列

<div class="exec-result w-table" :class="{'w-table_moving': dragState.dragging}">
                <div class="space-between">
                  <h4>查询结果</h4>
                  <p class="total-page">共{{totalNum}}条</p>
                </div>
                <el-table
                  id="dragTable"
                  :data="tableData"
                  border
                  ref="dragTable"
                  width="100%"
                  row-key="id"
                  :class="{'w-table_moving': dragState.dragging,'el-table--scrollable-y':true}"
                  :cell-class-name="cellClassName" 
                  :header-cell-class-name="headerCellClassName"
                  :header-cell-style="tableHeaderColor"
                  @sort-change="sortChange"
                  @header-contextmenu="rightClick">
                  <slot name="fixed"></slot>
                  <el-table-column
                    type="index"
                    :index="1+(pageNum-1)*pageSize"
                    label="序号"
                    width="50"
                    align="center">
                  </el-table-column>
                  <el-table-column 
                    v-for="(col, index) in columnName" 
                    :key="index"
                    :prop="col.otherFieldName"
                    :label="col.fieldAnnotation"
                    :header-align="col.align"
                    :column-key="index.toString()"
                    :label-class-name="''+col.index"
                    :class-name="col.adsTableName"
                    :render-header="renderHeader"
                    :sortable="col.fieldName !== 'plus'">
                    <template slot-scope="scope">
                      <a 
                        class="field-link"
                        v-if="col.fieldName === 'zzjgdm'" 
                        @click="showCompanyInfo(col,scope.row[col.otherFieldName])">
                        {{scope.row[col.otherFieldName]}}
                      </a>
                      <span 
                        v-else
                        :style="{display:'block','100%',textAlign:col.align}">
                        {{scope.row[col.otherFieldName]}}
                      </span>
                    </template>
                  </el-table-column>
                </el-table>
              </div>

以上是html部分

//表头渲染
    renderHeader (h, {column}) {
      if (column.label !== "+") {
        return h(
          'div', {
            'class': ['thead-cell'],
            on: {
              mousedown: ($event) => { this.handleMouseDown($event, column) },
              mousemove: ($event) => { this.handleMouseMove($event, column) }
            }
          }, [
            // 添加 <a> 用于显示表头 label
            h('a', column.label),
            // 添加一个空标签用于显示拖动动画
            h('span', {
              'class': ['virtual']
            })
          ]
        )
      } else {
        return h("i", {
          attrs: {
            id: "mainAdd",
            title: "添加计算列"
          },
          style: {
            fontSize: "24px",
            color: "#409EFF",
             "100%"
          },
          class: "el-icon-circle-plus-outline",
          on: {
            click: () => {
              this.addColumn()
            }
          }
        }, "")
      }
    },
    // 按下鼠标开始拖动
    handleMouseDown (e, column) {
      this.dragState.dragging = true
      this.dragState.start = parseInt(column.columnKey)
      this.moveIndex = parseInt(column.columnKey)
      // 给拖动时的虚拟容器添加宽高
      let table = document.getElementById('dragTable')
      let virtual = document.getElementsByClassName('virtual')
      for (let item of virtual) {
        item.style.height = table.clientHeight - 1 + 'px'
        item.style.width = item.parentElement.parentElement.offsetWidth + 'px'
      }
     document.addEventListener('mouseup', this.handleMouseUp);
    },
    // 鼠标放开结束拖动
    handleMouseUp (event) {
      this.dragColumn(this.dragState,event)
      // 初始化拖动状态
      this.dragState = {
        start: -9,
        end: -9,
        dragging: false,
        direction: undefined
      }
      document.removeEventListener('mouseup', this.handleMouseUp);
    },
    // 拖动中
    handleMouseMove (e, column) {
      if (this.dragState.dragging) {
        let index = parseInt(column.columnKey) // 记录起始列
        if (index - this.dragState.start !== 0) {
          this.dragState.direction = index - this.dragState.start < 0 ? 'left' : 'right' // 判断拖动方向
          this.dragState.end = parseInt(column.columnKey)
        } else {
          this.dragState.direction = undefined
        }
      } else {
        return false
      }
    },
    // 拖动易位
    dragColumn ({start, end, direction},event) {
      this.dragToCondition(event)
      let tempData = []
      let left = direction === 'left'
      let min = left ? end : start - 1
      let max = left ? start + 1 : end
      for (let i = 0; i < this.columnName.length; i++) {
        if (i === end) {
          tempData.push(this.columnName[start])
        } else if (i > min && i < max) {
          tempData.push(this.columnName[ left ? i - 1 : i + 1 ])
        } else {
          tempData.push(this.columnName[i])
        }
      }
      this.columnName = tempData
      this.$nextTick(() => {
        this.clearAllSortStyle()
        this.tableData = this.tableData.slice(0)
      })
    },
    //清除排序样式
    clearSortStyle (start,end) {
      let endClass = 'el-table_1_column_' + (end + 1)
      let endTd = document.getElementsByClassName(endClass)[0]
      let endClassList = endTd.classList
      let startClass = 'el-table_1_column_' + (start + 1)
      let startTd = document.getElementsByClassName(startClass)[0]
      let startClassList = startTd.classList

      if (startClassList.contains('descending')) {
        this.clearAllSortStyle()
        endClassList.add('descending')
        startClassList.remove('descending')
      } else if (startClassList.contains('ascending')) {
        this.clearAllSortStyle()
        endClassList.add('ascending')
        startClassList.remove('ascending')
      }
    },
    clearAllSortStyle () {
      let selfClassName = document.getElementsByClassName("is-sortable");
      let hasDescendingClassNameStt = false;
      let hasAscendingClassNameStt = false;
      for(let a =0;a<selfClassName.length;a++){
        // 清除倒序className
        hasDescendingClassNameStt = selfClassName[a].classList.contains('descending');
        if(hasDescendingClassNameStt){
          selfClassName[a].classList.remove('descending')
        }
        // 清除正序className
        hasAscendingClassNameStt = selfClassName[a].classList.contains('ascending');
        if(hasAscendingClassNameStt){
          selfClassName[a].classList.remove('ascending')
        }
      }
    },

以上是js部分

.w-table {
   .el-table .darg_start {
    background-color: #f3f3f3; 
    }
    .el-table th {
      padding: 0;
      .virtual{
        position: fixed;
        display: block;
        width: 0;
        height: 0;
        margin-left: -10px;
        background: none;
        border: none;
      }
      &.darg_active_left {
        .virtual {
          border-left: 2px dotted red;
          z-index: 99;
        }
      }
      &.darg_active_right {
        .virtual {
          border-right: 2px dotted red;
          z-index: 99;
        }
      }
    }
    .thead-cell {
      padding: 0;
      display: block;
      flex-direction: column;
      align-items: left;
      line-height:22px;
      cursor: pointer;
      overflow: initial;
      &:before {
        content: "";
        position: absolute;
        top: 0;
        left: 0;
        bottom: 0;
        right: 0;
      }
    }
    &.w-table_moving {
      .el-table th .thead-cell{
        cursor: move !important;
      }
      .el-table__fixed {
        cursor: not-allowed;
      }
    }
  }

以上是css部分

参考https://www.cnblogs.com/wisewrong/p/8820508.html

原文地址:https://www.cnblogs.com/snowRock/p/14715067.html