基于element UI 实现 table 列 拖拽

这篇具有很好参考价值的文章主要介绍了基于element UI 实现 table 列 拖拽。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

问题描述

在开发中遇到一个需求,即实现table列的拖拽,但是调研发现,大部分是基于sorttable.js这个包实现的,但是通过实际应用,发现sorttable.js用在操作element table 组件中并不是很舒服,总会莫名其妙的冒出一些异常bug,于是自行封装一个table 列拖拽组件。

难点概括

①element table header插槽应用

②drag知识点应用

③splice()方法理解

演示代码

<template>
  <div>
    <h1>基于element-ui table列拖拽实现</h1>
    <drag-head :head-columns="tableHead" :data="tableData"></drag-head>
  </div>
</template>
<script>
import DragHead from "./dragHead.vue";

export default {
  name: "DragHeadCase",

  components: { DragHead },

  data() {
    return {
      tableHead: [
        {
          label: "零零",
          prop: "v0",
          width: 150,
        },
        {
          label: "一一",
          prop: "v1",
          width: 150,
        },
        {
          label: "二二",
          prop: "v2",
          width: 150,
        },
        {
          label: "三三",
          prop: "v3",
          width: 150,
        },
        {
          label: "四四",
          prop: "v4",
          width: 300,
        },
        {
          label: "五五",
          prop: "v5",
        },
        {
          label: "六六",
          prop: "v6",
        },
        {
          label: "七七",
          prop: "v7",
        },
        {
          label: "八八",
          prop: "v8",
        },
        {
          label: "九九",
          prop: "v9",
        },
      ],

      tableData: [
        {
          v0: "2016-05-02",
          v1: "王小虎",
          v2: "上海",
          v3: "普陀区",
          v4: "上海市普陀区金沙江路 1518 弄",
          v5: 200333,
          v6: "2016-05-02",
          v7: "王小虎",
          v8: "上海",
          v9: "普陀区",
        },
        {
          v0: "2016-05-02",
          v1: "王小虎",
          v2: "上海",
          v3: "普陀区",
          v4: "上海市普陀区金沙江路 1518 弄",
          v5: 200333,
          v6: "2016-05-02",
          v7: "王小虎",
          v8: "上海",
          v9: "普陀区",
        },
        {
          v0: "2016-05-02",
          v1: "王小虎",
          v2: "上海",
          v3: "普陀区",
          v4: "上海市普陀区金沙江路 1518 弄",
          v5: 200333,
          v6: "2016-05-02",
          v7: "王小虎",
          v8: "上海",
          v9: "普陀区",
        },
        {
          v0: "2016-05-02",
          v1: "王小虎",
          v2: "上海",
          v3: "普陀区",
          v4: "上海市普陀区金沙江路 1518 弄",
          v5: 200333,
          v6: "2016-05-02",
          v7: "王小虎",
          v8: "上海",
          v9: "普陀区",
        },
        {
          v0: "2016-05-02",
          v1: "王小虎",
          v2: "上海",
          v3: "普陀区",
          v4: "上海市普陀区金沙江路 1518 弄",
          v5: 200333,
          v6: "2016-05-02",
          v7: "王小虎",
          v8: "上海",
          v9: "普陀区",
        },
      ],
    };
  },
};
</script>

table 列 拖拽组件实现代码

<template>
  <div style="width: 1000px">
    <el-table
      ref="elTable"
      border
      style="width: 100%"
      v-bind="$attrs"
      v-on="$listeners"
      :key="headKey"
      :cell-class-name="cellClassName"
      :header-cell-class-name="cellClassName"
    >
      <!-- 循环表头 -->
      <template v-for="(col, index) in tableHead">
        <el-table-column
          :key="index"
          :prop="col.prop"
          :align="col.align || 'center'"
          :width="col.width || 100"
        >
          <!-- 通过插槽为表头绑定mousedown和dragover方法 -->
          <template slot="header" slot-scope="{ column, $index }">
            <span
              @mousedown="handleMounseDown($event, column, $index)"
              @dragover="handleDragover($event, column, $index)"
            >
              {{ col.label }}
            </span>
          </template>
        </el-table-column>
      </template>
    </el-table>
  </div>
</template>

<script>
export default {
  props: {
    headColumns: Array,
  },

  mounted() {
    /** 备用操作(如果需要对headColumns数组操作) */
    this.tableHead = this.headColumns;
  },

  data() {
    return {
      tableHead: [],

      // 拖拽状态
      dragState: {
        start: -3, // 起始元素的 index 防止初始化cellStyle时序号、展开等默认样式改变,最好小于-3
        end: -3, // 移动鼠标时所覆盖的元素 index
        dragging: false, // 是否正在拖动
        direction: undefined, // 拖动方向
      },

      headKey: "dragHead", // 表头数组变换位置时,重绘table(不更新该值,表头数组变化时,页面不会改变)

      scrollX: 0, // 初始x轴scroll位置(用于定位X轴滚动条)
    };
  },

  methods: {
    /** 鼠标摁下触发 */
    handleMounseDown(e, column, $index) {
      this.dragState.dragging = true;
      this.dragState.start = parseInt($index - 0);
      // 添加鼠标抬起事件  消除鼠标摁下立刻松开问题
      document.addEventListener("mouseup", this.handleMouseUp);
      // 添加拖拽结束事件
      document.addEventListener("dragend", this.handleMouseUp);

      // 对选中的表头允许其拖拽
      const dragclass = ".el-table__header-wrapper ." + column.id;
      const dragDom = document.querySelectorAll(dragclass);
      dragDom.forEach((dom) => {
        // 允许表头块可以被拖拽 draggable 属性 不允许拖拽dragover等相关拖拽事件无法触发
        dom.setAttribute("draggable", true);
      });
    },

    /** 鼠标在拖拽移动时触发 */
    handleDragover(e, column, $index) {
      if (this.dragState.dragging) {
        // 获取当前滚动条的位置
        const scrollDom = this.$refs.elTable.bodyWrapper;
        this.scrollX = scrollDom.scrollLeft;
        const index = parseInt($index - 0); // 记录起始列
        /** 实时更改鼠标处于表头的位置 */
        if (index - this.dragState.start !== 0) {
          this.dragState.direction =
            index - this.dragState.start < 0 ? "left" : "right"; // 判断拖动方向
          this.dragState.end = parseInt($index - 0);
        } else {
          this.dragState.end = this.dragState.start;
          this.dragState.direction = null;
        }
      }
    },

    /** 鼠标抬起或拖拽结束触发 */
    handleMouseUp() {
      // 更新拖拽后的表头
      this.headDraged(this.dragState);
      const { end } = this.dragState;
      // 初始化拖动状态
      this.dragState = {
        start: end, //记录最后拖动的位置
        end: -9,
        dragging: false,
        direction: undefined,
      };
      document.removeEventListener("mouseup", this.handleMouseUp);
      document.removeEventListener("dragend", this.handleMouseUp);

      setTimeout(() => {
        // 重置拖拽状态
        this.dragState.start = -9;
      }, 500);
    },

    // 更新拖拽后的表头
    headDraged({ start, end, direction }) {
      if (direction) {
        const originColumn = this.tableHead[start];
        // 有位置交换时,原先位置的元素删除,再在目标处插入
        this.tableHead.splice(start, 1);
        this.tableHead.splice(end, 0, originColumn);
        this.headKey = new Date().getTime() + ""; // 更新table key值
        this.$nextTick(() => {
          // 因为表头重绘后滚动条会移到最左端初始位置,因此如果是在中间部分拖拽,还需要把滚动条在定位到该位置
          this.$refs.elTable.bodyWrapper.scrollLeft = this.scrollX;
        });
      }
    },

    // 拖动虚线样式设置
    cellClassName({ columnIndex }) {
      const { start, end, direction } = this.dragState;
      const target = columnIndex - 0;
      if (target === start) {
        // 被移动的元素
        return "drag_start";
      } else if (target === end) {
        // 要移动的位置
        return `drag_end_${direction}`;
      }
      return "";
    },
  },
};
</script>

<style lang="scss" scoped>
::v-deep .el-table {
  .drag_start {
    opacity: 0.8;
    background-color: rgba(0, 0, 0, 0.938);
    color: #f3e8e8fd;
    transition: all 0.3s cubic-bezier(0.23, 1, 0.32, 1);
  }
  .drag_end_left {
    border-left: 2px dotted rgba(0, 0, 0, 0.938);
  }
  .drag_end_right {
    border-right: 2px dotted rgba(0, 0, 0, 0.938);
  }
}
</style>

然后我在操作的时候碰到一个报错

[Violation ] Added non-passive event listener to ascroll- blocking 'mousewheel’event Consider marking event handler as ’ passive’to make the page more responsive. See https: com/feature/574554 3795965952

翻译:

[冲突]在ascroll中添加了非被动事件侦听器-阻塞“mousewheel”事件考虑将事件处理程序标记为“passive”,以使页面更具响应性。参见https:com/feature/574554 3795965952

解决办法:

npm i default-passive-events -S
main.js import 'default-passive-events'

最后

该组件目前仅支持最简单的拖拽效果,后续开发出兼容fixed、checkbox、expand 以及操作列的组件会及时更新文章,有兴趣的朋友可以点赞收藏。

参考文献

基于element UI 实现 table 列 拖拽_element table列拖拽_淡然自若_blog的博客-CSDN博客

Added non-passive event listener to ascroll- blocking ‘mousewheel‘event Consider marking event handl_绅士的可怖的博客-CSDN博客文章来源地址https://www.toymoban.com/news/detail-670786.html

到了这里,关于基于element UI 实现 table 列 拖拽的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • vue element ui table组件列宽可以拖拽调整大小,某一列可以禁止拖拽调整大小

     只需要在 el-table-column 标签中添加 :resizable=\\\"false\\\" 即可   参考链接: https://chat.xutongbao.top/

    2024年01月21日
    浏览(42)
  • 基于element-ui的table实现树级表格操作及单元格合并

    如题,公司业务需求,数据结构比较复杂,需要在一张表内实现多级树状数据展示及同属性的单元格合并,并在表格内实现增删改操作。 网上翻阅了很多实例,没有能解决所有需求的案例,于是自己实现了一套。 时间匆忙,逻辑有优化的地方还请无偿指出! 最终效果如下

    2024年02月14日
    浏览(35)
  • Vue+Element-UI 实现前端分页功能,利用el-table和el-pagination组件实现表格前端分页

    Vue+Element-UI 实现前端分页功能,利用el-table和el-pagination组件实现表格前端分页:         当table的数据量比较大的时候,一个屏幕展示不出全部的数据,这个时候就需要分页显示。而多数情况下都是做的后端分页,就是将分页参数和查询条件一并传到后端,后端将当前页要

    2024年01月20日
    浏览(43)
  • JavaScript与前端框架Element UI

    一、JavaScript概述 JavaScript(简称JS)是一种轻量级、解释性的、基于对象的脚本语言,用于Web开发中的客户端脚本。它是HTML和CSS的一部分,用于在浏览器中实现动态交互。 JavaScript最初由Netscape公司的Brendan Eich于1995年开发,旨在为网页添加动态内容。不同于编译型语言如Java和

    2024年04月29日
    浏览(33)
  • 基于vue+Element UI的文件上传(可拖拽上传)

    drag: 支持拖拽上传 action:必选参数,上传的地址 ref:这里主要是用于文件上传完成后清除文件的 on-remove:文件列表移除文件时的钩子 auto-upload:是否在选取文件后立即进行上传 on-change:文件状态改变时的钩子,添加文件、上传成功和上传失败时都会被调用 注:这里使用的

    2023年04月08日
    浏览(33)
  • 基于Element-ui 封装穿梭框(左侧树 右侧列表,可全选,列表可拖拽)

    Element-ui提供的穿梭框只支持列表,根据实际需求自己写了一个左边是树结构,右边是列表结构的穿梭框,(如果需要两边都是树结构的话,需要把右侧的逻辑参考左侧改一改)拖拽使用了 vuedraggable 插件

    2024年02月11日
    浏览(41)
  • vue+element ui实现图片上传并拖拽进行图片排序

    用到的技术栈: vue2 element Ui vue-dragging 第一步: 安装 第二步: 引入 Video_23-11-13_10-17-30 end~~~ 如有错误或观点不一致的请评论留言共同讨论,本人前端小白一枚,根据自己实际项目遇到的问题进行总结分享,谢谢大家的阅读!

    2024年01月24日
    浏览(41)
  • vue 实现element-ui 表格的行拖拽排序 (Sortable)

    Sortable它是一个比较简单好用的拖拽排序工具 1.首先是安装下载Sortable (npm install sortablejs --save) 2.在要进行拖拽的页面引入Sortable (import Sortable from \\\'sortablejs\\\') 3.写个方法去处理你需要的数据,这里需要注意一下需要等待元素渲染完成后再执行此方法  4.处理好数据以后再去

    2024年02月11日
    浏览(46)
  • vue+element ui+vuedraggable实现表格内不同格子间标签的拖拽

    最近有个需求是实现在表格内上下不同格子间标签的拖拽,然而element ui并没有提供此类api,后面我导入vuedraggable包实现了此需求,效果见视频。 demo视频: element ui表格内标签拖拽demo 首先要去下载vuedraggable包 去package.json文件里看包是否下载成功 下载完成后新建页面 页面完整

    2024年04月29日
    浏览(24)
  • Element Ui Tree组件实现增、删、改、查、拖拽节点 的树形结构

    介绍:首先组件 | Element官网某些功能都具备了,这里我就把这些功能结合在一起更完美的使用,其次 编辑节点 官网是没有实例,所以这里搞了一套较完整的功能,其次编辑和添加,这里直接使用了弹窗(顾及到多个参数设置),接下来效果图展示! 效果图如下: 1,其中点

    2024年02月13日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包