用dragstart、drag、dragend、dragover、drop、dragleave实现针对表格列的顺序进行拖拽排序(附带实现选择某几列数据显示或隐藏)

 

特性

  1. 可以显示隐藏某一列
  2. 可以圈选显示隐藏所有列(禁用列不受状态影响) 
  3. 可以拖拽列名进行前后排序
<template>
  <div :class="$options.name">
    <el-dropdown :show-timeout="0" :placement="`bottom`">
      <el-link :underline="false" style="cursor: default"
        >表格列设置
        <el-tooltip
          :enterable="false"
          effect="dark"
          :content="`可以上下拖拽改变列顺序`"
          placement="top"
          :transition="`none`"
        >
          <i class="el-icon-question"></i>
        </el-tooltip>
        <i class="el-icon-arrow-down"></i>
      </el-link>
      <el-dropdown-menu
        slot="dropdown"
        style="transition: none; overflow-y: auto; max-height: 400px; margin-top: 5px"
        ><el-dropdown-item style="padding: 0">
          <el-checkbox
            style="width: 100%; box-sizing: border-box; padding: 0 20px"
            :indeterminate="checkedHalf"
            :disabled="!tableColumns.some((v) => !v.disabled)"
            v-model="checkedAll"
            @change="changeCheckedAll"
            @click.native.stop
            >全选</el-checkbox
          ></el-dropdown-item
        >
        <el-dropdown-item
          style="padding: 0"
          v-for="(item, index) in tableColumns"
          :key="index"
          :divided="item.divided"
        >
          <div
            :draggable="!item.disabled"
            style="
              box-sizing: border-box;
              border: 2px dashed transparent;
              border-left: none;
              border-right: none;
            "
            @dragstart="dragstart($event, index)"
            @drag="drag"
            @dragend="dragend"
            @dragover="dragover"
            @drop="drop($event, index)"
            @dragleave="dragleave"
          >
            <el-checkbox
              style="width: 100%; box-sizing: border-box; padding: 0 20px"
              :disabled="item.disabled"
              v-model="item.checked"
              @click.native.stop
              >{{ item.label }}</el-checkbox
            >
          </div></el-dropdown-item
        >
      </el-dropdown-menu>
    </el-dropdown>

    <el-table :data="tableData">
      <el-table-column type="selection" width="50" />
      <el-table-column type="index" label="序号" width="60" />

      <!-- 主要列 BEGIN---------------------------------------- -->
      <el-table-column
        v-for="(a, i) in tableColumns"
        v-if="a.checked"
        :key="i"
        :prop="a.prop"
        :label="a.label"
        :width="a.width || `auto`"
      />
      <!-- 主要列 END---------------------------------------- -->

      <el-table-column label="操作" width="150">
        <template slot-scope="scope">
          <el-button size="mini" type="primary">修改</el-button>
          <el-button size="mini" type="danger">删除</el-button>
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>
<script>
export default {
  data() {
    return {
      // 表格列字段----------------------------------------
      checkedHalf: false,
      checkedAll: false,
      tableColumns: [
        { prop: "ZD1", label: "字段名称1", width: 110, checked: true, },
        { prop: "ZD2", label: "字段名称2", width: 200, checked: true, disabled: true },
        { prop: "ZD3", label: "字段名称3", width: 110, checked: true, },
        { prop: "ZD4", label: "字段名称4", width: 110 },
        { prop: "ZD5", label: "字段名称5", width: 110 },
      ],
      // ----------------------------------------
      tableData: [
        {
          ZD1: "字段1的值-1",
          ZD2: "字段2的值-1",
          ZD3: "字段3的值-1",
          ZD4: "字段4的值-1",
          ZD5: "字段5的值-1",
        },
        {
          ZD1: "字段1的值-2",
          ZD2: "字段2的值-2",
          ZD3: "字段3的值-2",
          ZD4: "字段4的值-2",
          ZD5: "字段5的值-2",
        },
        {
          ZD1: "字段1的值-3",
          ZD2: "字段2的值-3",
          ZD3: "字段3的值-3",
          ZD4: "字段4的值-3",
          ZD5: "字段5的值-3",
        },
        {
          ZD1: "字段1的值-4",
          ZD2: "字段2的值-4",
          ZD3: "字段3的值-4",
          ZD4: "字段4的值-4",
          ZD5: "字段5的值-4",
        },
        {
          ZD1: "字段1的值-5",
          ZD2: "字段2的值-5",
          ZD3: "字段3的值-5",
          ZD4: "字段4的值-5",
          ZD5: "字段5的值-5",
        },
      ], //表格数据
    };
  },
  watch: {
    tableColumns: {
      handler(newValue, oldValue) {
        if (newValue && Object.keys(newValue).length) {
          this.checkedHalf =
            newValue.some((v) => v.checked) && newValue.some((v) => !v.checked); //部分选中
          newValue.every((v) => v.checked) &&
            ((this.checkedAll = true), (this.checkedHalf = false)); //全选中
          this.checkedHalf && (this.checkedAll = false); //未全选中
        }
      },
      deep: true, //深度监听
      immediate: true, //立即执行
    },
  },

  methods: {
    changeCheckedAll(checked) {
      let allowItems = this.tableColumns.filter((v) => !v.disabled); //未被禁用的选项
      this.checkedAll = allowItems.some((v) => !v.checked); //在未被禁用的选项中,只要有一个未勾选,点击“全选”就是全选,否者就是全不选
      allowItems.forEach((v) => this.$set(v, "checked", this.checkedAll));
    },
    // 被拖拽物体的监听事件----------------------------------------
    dragstart(e, index) {
      e.dataTransfer.setData("fromIndex", index); //传递拖拽起始位置索引
    },
    drag(e) {
      e.currentTarget.style.opacity = 0.618; //被拖拽元素透明
    },
    dragend(e) {
      e.currentTarget.style.opacity = 1; //被拖拽元素恢复透明
    },
    // 放置区域的监听事件----------------------------------------
    dragover(e) {
      let et = e.currentTarget;
      let lessThanHalf = e.offsetY < et.offsetHeight / 2; //向下拖动鼠标未超过被放置区域一半高度(如果放入物体包含很多深层级子元素,需要在拖拽过程设置子元素pointer-events: none;)
      et.style.borderTopColor = lessThanHalf ? `#409EFF` : `transparent`; //上边线显示
      et.style.borderBottomColor = !lessThanHalf ? `#409EFF` : `transparent`; //下边线显示
      e.preventDefault();
    },
    drop(e, index) {
      let et = e.currentTarget;
      et.style.borderColor = `transparent`;
      let lessThanHalf = e.offsetY < et.offsetHeight / 2; //向下拖动鼠标未超过被放置区域一半高度(如果放入物体包含很多深层级子元素,需要在拖拽过程设置子元素pointer-events: none;)
      let fromIndex = e.dataTransfer.getData("fromIndex"); //拖拽起始位置索引
      let toIndex = index; //拖拽到的目标位置索引
      if (fromIndex == toIndex) return; //一样的位置就不改变顺序了
      toIndex =
        fromIndex < toIndex
          ? lessThanHalf
            ? index - 1
            : index
          : lessThanHalf
          ? index
          : index + 1; //拖拽到不同的目标位置索引(注意细节:从下往上拖拽 和 从上往下 拖拽索引的大小不一样)
      this.$g.array.moveArrayElement(this.tableColumns, fromIndex, toIndex); //移动目标元素
    },
    dragleave(e) {
      e.currentTarget.style.borderColor = `transparent`; //清空边框线
    },
  },
};
</script>

应用到了将数组指定索引位置的元素 移动到 目标索引位置,且不改变其他元素原本的顺序,注意这个不是对调元素位置,是移动某一个元素位置不影响其他元素顺(使用场景:拖拽改变数据的顺序,点击上下左右箭头移动元素顺序)-CSDN博客文章浏览阅读84次,点赞2次,收藏3次。【代码】将数组指定索引位置的元素 移动到 目标索引位置(使用场景:拖拽改变数据的顺序,点击上下左右箭头移动元素顺序)https://blog.csdn.net/qq_37860634/article/details/136788107

 用第三方插件实现表格的行拖拽排序基于sortablejs实现拖拽element-ui el-table表格行进行排序-CSDN博客【代码】基于sortablejs实现拖拽element-ui el-table表格行进行排序。https://blog.csdn.net/qq_37860634/article/details/136791080

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值