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

简介: 用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"
        ><el-dropdown-item>
          <el-checkbox
            :indeterminate="checkedHalf"
            :disabled="!tableColumns.some((v) => !v.disabled)"
            v-model="checkedAll"
            @change="changeCheckedAll"
            @click.native.stop
            >全选</el-checkbox
          ></el-dropdown-item
        >
        <el-dropdown-item
          v-for="(item, index) in tableColumns"
          :key="index"
          :divided="item.divided"
          style="padding: 0"
        >
          <div
            :draggable="!item.disabled"
            style="
              padding: 0 20px;
              box-sizing: border-box;
              border: 2px dashed transparent;
            "
            @dragstart="dragstart($event, index)"
            @drag="drag"
            @dragend="dragend"
            @dragover="dragover"
            @drop="drop($event, index)"
            @dragleave="dragleave"
          >
            <el-checkbox
              :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 },
        { prop: "ZD2", label: "字段名称2", width: 200, checked: true, disabled: true },
        { prop: "ZD3", label: "字段名称3", width: 110 },
        { 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; //向下拖动鼠标未超过被放置区域一半高度
      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; //向下拖动鼠标未超过被放置区域一半高度
      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>

应用到了

image.png

用第三方插件实现表格的行拖拽排序

image.png

相关文章
|
JSON 数据格式 容器
Layui 内置方法 - layer.photos(相册层)
Layui 内置方法 - layer.photos(相册层)
1988 0
|
缓存 达摩院 Kubernetes
数据缓存系列分享(六):通义千问Qwen-14B大模型快速体验
阿里达摩院近期对通义千问大模型 Qwen-14B 进行了开源(之前开源的是Qwen-7B模型),目前在ModelScope和HuggingFace上均可直接下载。关于Qwen-7B的搭建可以参考我们之前的文章:数据缓存系列分享(五):开源大语言模型通义千问快速体验版,本文将使用一样的方式打开Qwen-14B,快速体验一下。
2027 0
数据缓存系列分享(六):通义千问Qwen-14B大模型快速体验
|
JavaScript 程序员 Java
js根据当前时间获取指定范围内的时间段日期
版权声明:本文为博主原创文章,如需转载,请标明出处。 https://blog.csdn.net/alan_liuyue/article/details/78311491 一.
2774 0
|
资源调度 JavaScript
Vue2拖拽插件(vuedraggable)
这篇文章介绍了如何在Vue 3框架中使用`vuedraggable`插件来实现拖拽功能,并提供了插件的安装、配置和事件处理的示例。
1075 1
Vue2拖拽插件(vuedraggable)
一个简单的Vue2例子讲明白拖拽drag、移入dragover、放下drop的触发机制先后顺序
一个简单的Vue2例子讲明白拖拽drag、移入dragover、放下drop的触发机制先后顺序
|
12月前
|
存储 前端开发 JavaScript
🚀前端轻松实现网页内容转换:一键复制、保存图片及生成 Markdown
在现代前端开发中,提升用户的交互体验至关重要。本文将详细介绍如何使用 HTML2Canvas 和 Turndown 两个强大的 JavaScript 库,实现将网页选中文本转化为图片并保存或复制到剪贴板,或将内容转换为 Markdown 格式。文章包含核心代码实现、技术细节和功能拓展方向,为开发者提供了一个轻量级的解决方案,提升用户体验。
955 68
|
JavaScript 前端开发
【Vue 3】如何实现动态表单生成器的拖拽功能?
【Vue 3】如何实现动态表单生成器的拖拽功能?
|
11月前
|
监控 前端开发 JavaScript
前端稳定性工具-Sentry
【11月更文挑战第9天】Sentry 是一个开源的错误和性能监控平台,支持多种编程语言和框架。它能够捕获前端应用中的各种错误和性能问题,提供详细的错误信息和用户行为关联,帮助开发团队快速定位和解决问题,优化应用性能。但需注意隐私保护、数据准确性和成本控制。
970 3
|
安全 Devops 测试技术
阿里云云效
阿里云云效
509 3
|
缓存 JavaScript 前端开发
npm常用命令详解与实践
npm常用命令详解与实践