awe-dnd 实现el-table动态拖拽设置表头

项目场景:

VUE+Element 实现el-table动态设置表头(可拖拽)


问题描述:

由于Element组件不支持动态拖拽设置表头,所以使用awe-dnd插件实现拖拽效果


实现方法:

安装依赖

npm install awe-dnd --save

全局注册或局部注册

1、全局注册

  • 在main.js文件中
import VueDND from 'awe-dnd';
// 注册-拖拽组件
Vue.use(VueDND);

2、局部注册(页面内注册)

import Vue from 'vue'
import VueDND from 'awe-dnd'
Vue.use(VueDND)

页面使用

1、HTML

<template>
<div class="table-box">
            <el-table
              v-loading="loading"
              :data="tableData"
              style="width: 100%"
              :header-cell-style="{
                background: '#FAFAFA',
                color: '#000000',
                'font-family': 'Source Han Sans CN',
                'font-size': '14px',
                'font-weight': '400'
              }"
            >
              <!-- checkedTitle -->
              <el-table-column
                v-for="(title, titleIndex) in checkedTitleList"
                :key="titleIndex"
                :prop="title.column"
                :label="title.text"
                width="180"
                :sortable="title.sortable"
              >
                <template slot-scope="{ row }">
                  <span>11</span>
                </template>
              </el-table-column>
              <el-table-column
                label="操 作"
                width="260"
                fixed="right"
                class-name="small-padding fixed-width"
              >
                <template slot-scope="{ row }">
                  <div class="level buttons" style="padding: 0 5px">
                    <div
                      v-permission="{ action: 'auxiliary.plan:update' }"
                      class="details-btn"
                      @click="handleUpdate(row)"
                    >
                      编辑
                    </div>
                  </div>
                </template>
              </el-table-column>
            </el-table>
            <el-popover
              v-model="visibleAllTitle"
              placement="bottom"
              width="200"
              trigger="manual"
              popper-class="select-sort-title-popover"
            >
              <div class="select-sort-title">
                <p class="custom-column">自定义列</p>
                <p class="sorting">勾选需要显示的列,拖动列名进行排序。</p>
                <el-checkbox-group
                  v-model="checkedTitle"
                  @change="setTableHeader"
                >
                  <el-checkbox
                    v-for="title in allTitleList"
                    :key="title"
                    v-dragging="{
                      item: title,
                      list: allTitleList,
                      group: 'title'
                    }"
                    :label="title"
                  >{{ title }}</el-checkbox>
                </el-checkbox-group>
              </div>
              <i
                slot="reference"
                class="el-icon-setting"
                @click="visibleAllTitle = !visibleAllTitle"
              />
            </el-popover>
          </div>
</template>

2、javascript

注意:由于el-checkbox-groupv-model没办法绑定一个对象,会导致给不了默认值,所以复选框绑定的是字符串数组,选择或拖拽之后使用数组过滤出对应的title列表

<script>
import lodash from 'lodash'
import Vue from 'vue'
import VueDND from 'awe-dnd'
Vue.use(VueDND)
const allTitleText = [
  '表头1',
  '表头2',
  '表头3',
  '表头4',
  '表头5',
  '表头6',
  '表头7',
  '表头8',
  '表头9',
  '表头10'
]
const allTitleListClone = [
  {
    text: '表头1',
    column: 'orderNumber',
    sortable: true
  },
  {
    text: '表头2',
    column: 'materialCode',
    sortable: false
  },
  {
    text: '表头3',
    column: 'workshopName',
    sortable: false
  },
  { text: '表头4', column: 'type', sortable: false },
  { text: '表头5', column: 'planNum', sortable: false },
  {
    text: '表头6',
    column: 'planCompleteTime',
    sortable: false
  },
  { text: '表头7', column: 'deliveryDate', sortable: false },
  { text: '表头8', column: 'orderDate', sortable: false },
  {
    text: '表头9',
    column: 'currentInventory',
    sortable: false
  },
  { text: '表头10', column: 'isfully', sortable: false }
]
export default {
  name: 'AuxiliaryPlan',
  data() {
    return {
    	tableData: [{}, {}],
      //   设置表头
      visibleAllTitle: false,
      checkedTitle: [],
      checkedTitleList: lodash.cloneDeep(allTitleListClone),
      allTitleList: lodash.cloneDeep(allTitleText),
      draggedList: lodash.cloneDeep(allTitleText),
    }
  },
   mounted() {
    this.dropEvent()
    this.checkedTitle = lodash.cloneDeep(allTitleText)
  },
   methods: {
    getList() {},
    // 拖拽设置表头
    /**
     * @description:拖拽事件,选中的checkedCities 根据拖拽的list 的顺序排序
     * @param {*}
     * @return {*}
     */
    dropEvent() {
      this.$dragging.$on('dragged', ({ value }) => {
        this.draggedList = value.list
        this.filterCheckedTitleList()
      })
    },
    setTableHeader() {
      this.filterCheckedTitleList()
    },
    filterCheckedTitleList() {
      this.checkedTitle.sort((a, b) => {
        return this.draggedList.indexOf(a) - this.draggedList.indexOf(b)
      })
      const tempList = lodash.cloneDeep(this.checkedTitle)
      allTitleListClone.forEach(title => {
        const index = this.checkedTitle.findIndex(item => title.text === item)
        if (index !== -1) {
          tempList[index] = title
        }
      })
      this.checkedTitleList = tempList
    },
   }
}
</script>

3、CSS

注意:由于使用了el-popover弹出框,需要在body内去全局修改样式才会生效,避免更改到其他地方,需要定义一个唯一的classel-popover需要使用popper-class指定对应的class


.select-sort-title-popover {
  background: #ffffff;
  border: 1px solid #1890ff;
  box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.16);
  padding: 20px;
  width: 220px !important;

  .select-sort-title {
    font-size: 14px;
    font-family: Source Han Sans CN;
    font-weight: 400;

    p {
      width: 100%;
      margin: 0;
    }

    .custom-column {
      color: #333333;
      margin-bottom: 12px;
    }

    .sorting {
      font-size: 10px;
      transform: scale(0.8);
      color: #999999;
      margin-left: -18px;
      width: 122%;
    }

    .el-checkbox {
      line-height: 30px;

      .el-checkbox__label {
        font-size: 12px;
        padding: 0 10px 0 5px;
        margin-left: 10px;
      }
    }

    .is-checked {
      .el-checkbox__label {
        background: #E7F4FF;
      }

    }
  }

  .popper__arrow {
    border-bottom-color: #1890ff !important;
  }
}

拖拽的关键代码

 v-dragging="{
                      item: title,
                      list: allTitleList,
                      group: 'title'
                    }"
  • 页面拖拽触发的方法
dropEvent() {
      this.$dragging.$on('dragged', ({ value }) => {
        this.draggedList = value.list
        this.filterCheckedTitleList()
      })
    },
    filterCheckedTitleList() {
      this.checkedTitle.sort((a, b) => {
        return this.draggedList.indexOf(a) - this.draggedList.indexOf(b)
      })
      const tempList = lodash.cloneDeep(this.checkedTitle)
      allTitleListClone.forEach(title => {
        const index = this.checkedTitle.findIndex(item => title.text === item)
        console.log(index, 'index')
        if (index !== -1) {
          tempList[index] = title
        }
      })
      this.checkedTitleList = tempList
    },
  • 官方文档:https://www.npmjs.com/package/awe-dnd

效果图

  • 拖拽前
    awe-dnd 实现el-table动态拖拽设置表头_第1张图片
  • 拖拽后
  • awe-dnd 实现el-table动态拖拽设置表头_第2张图片

你可能感兴趣的:(vue,ElementUI,awe-dnd,javascript,vue.js,elementui,awe)