Vue + Element UI el-table + sortablejs 行、列拖拽排序

news2024/11/14 22:01:32

实现Element UI中的el-table表格组件的行和列的拖拽排序

使用 Vue3 + Element Plus UI + sortablejs

安装sortablejs

pnpm install sortablejs

行拖拽

基本实现

效果
在这里插入图片描述

<script setup>
import { onMounted, ref } from "vue";
import Sortable from "sortablejs";

const tableData = ref([
  {
    id: 1,
    date: "2016-05-02",
    name: "王小虎111",
    age: 21,
    address: "上海市普陀区金沙江路 1518 弄",
  },
  {
    id: 2,
    date: "2016-05-04",
    name: "王小虎222",
    age: 22,
    address: "上海市普陀区金沙江路 1517 弄",
  },
  {
    id: 3,
    date: "2016-05-01",
    name: "王小虎333",
    age: 23,
    address: "上海市普陀区金沙江路 1519 弄",
  },
  {
    id: 4,
    date: "2016-05-03",
    name: "王小虎444",
    age: 24,
    address: "上海市普陀区金沙江路 1516 弄",
  },
  {
    id: 5,
    date: "2016-05-08",
    name: "王小虎555",
    age: 25,
    address: "上海市普陀区金沙江路 1518 弄",
  },
]);

onMounted(() => {
  rowDrop();
});

/**
 * 行拖拽排序
 */
function rowDrop() {
  // 要侦听拖拽响应的DOM对象
  const tbody = document.querySelector(".el-table__body-wrapper tbody");
  const data = tableData.value;
  Sortable.create(tbody, {
    // handle: ".el-icon-rank",
    ghostClass: "target-row-class",
    // 结束拖拽后的回调函数
    onEnd({ newIndex, oldIndex }) {
      // 将oldIndex位置的数据删除并取出,oldIndex后面位置的数据会依次前移一位
      const currentRow = data.splice(oldIndex, 1)[0];
      // 将被删除元素插入到新位置(currRow表示上面的被删除数据)
      data.splice(newIndex, 0, currentRow);
    },
  });
}
</script>

<template>
  <el-table
    ref="table"
    :data="tableData"
    style="width: 100%"
    border
    row-key="id"
  >
    <el-table-column prop="date" label="日期" />
    <el-table-column prop="name" label="姓名" />
    <el-table-column prop="age" label="年龄" />
    <el-table-column prop="address" label="地址" />
    <!--<el-table-column align="center" width="55">-->
    <!--  <i class="el-icon-rank" />-->
    <!--</el-table-column>-->
  </el-table>
</template>

<style scoped lang="less">
.el-table {
  ::v-deep {
    .target-row-class {
      background: #f0f9eb;
    }
  }
}
</style>

禁止某几行拖拽

效果
在这里插入图片描述

<script setup>
import { onMounted, ref } from "vue";
import Sortable from "sortablejs";

const tableData = ref([
  {
    id: 1,
    date: "2016-05-02",
    name: "王小虎111",
    age: 21,
    address: "上海市普陀区金沙江路 1518 弄",
  },
  {
    id: 2,
    date: "2016-05-04",
    name: "王小虎222",
    age: 22,
    address: "上海市普陀区金沙江路 1517 弄",
  },
  {
    id: 3,
    date: "2016-05-01",
    name: "王小虎333",
    age: 23,
    address: "上海市普陀区金沙江路 1519 弄",
  },
  {
    id: 4,
    date: "2016-05-03",
    name: "王小虎444",
    age: 24,
    address: "上海市普陀区金沙江路 1516 弄",
  },
  {
    id: 5,
    date: "2016-05-08",
    name: "王小虎555",
    age: 25,
    address: "上海市普陀区金沙江路 1518 弄",
  },
]);

onMounted(() => {
  rowDrop();
});

/**
 * 行拖拽排序
 */
function rowDrop() {
  // 要侦听拖拽响应的DOM对象
  const tbody = document.querySelector(".el-table__body-wrapper tbody");
  const data = tableData.value;
  Sortable.create(tbody, {
    // handle: ".el-icon-rank",
    ghostClass: "target-row-class",
    // 匹配的元素将不会触发拖动
    filter: ".filtered",
    // 拖拽移动事件,返回false取消移动
    onMove: function ({ related }) {
      return related.className.indexOf("filtered") === -1;
    },
    // 结束拖拽后的回调函数
    onEnd({ newIndex, oldIndex }) {
      // 将oldIndex位置的数据删除并取出,oldIndex后面位置的数据会依次前移一位
      const currentRow = data.splice(oldIndex, 1)[0];
      // 将被删除元素插入到新位置(currRow表示上面的被删除数据)
      data.splice(newIndex, 0, currentRow);
    },
  });
}

// 设置ID为1和5的行禁止拖拽
function tableRowClassName({ row, rowIndex }) {
  const freezeList = [1, 5];
  return freezeList.includes(row.id) ? "filtered" : "";
}
</script>

<template>
  <el-table
    ref="table"
    :data="tableData"
    style="width: 100%"
    border
    row-key="id"
    :row-class-name="tableRowClassName"
  >
    <el-table-column prop="date" label="日期" />
    <el-table-column prop="name" label="姓名" />
    <el-table-column prop="age" label="年龄" />
    <el-table-column prop="address" label="地址" />
    <!--<el-table-column align="center" width="55">-->
    <!--  <i class="el-icon-rank" />-->
    <!--</el-table-column>-->
  </el-table>
</template>

<style scoped lang="less">
.el-table {
  ::v-deep {
    .target-row-class {
      background: #f0f9eb;
    }
	// 禁止拖拽行背景色
    .filtered {
      background-color: #1db1e7 !important;
    }
  }
}
</style>

列拖拽

基本实现

效果
在这里插入图片描述

<script setup>
import { onMounted, ref } from "vue";
import Sortable from "sortablejs";

const columns = ref([
  { label: "日期", prop: "date" },
  { label: "姓名", prop: "name" },
  { label: "年龄", prop: "age" },
  { label: "地址", prop: "address" },
]);

const tableData = ref([
  {
    id: 1,
    date: "2016-05-02",
    name: "王小虎111",
    age: 21,
    address: "上海市普陀区金沙江路 1518 弄",
  },
  {
    id: 2,
    date: "2016-05-04",
    name: "王小虎222",
    age: 22,
    address: "上海市普陀区金沙江路 1517 弄",
  },
  {
    id: 3,
    date: "2016-05-01",
    name: "王小虎333",
    age: 23,
    address: "上海市普陀区金沙江路 1519 弄",
  },
  {
    id: 4,
    date: "2016-05-03",
    name: "王小虎444",
    age: 24,
    address: "上海市普陀区金沙江路 1516 弄",
  },
  {
    id: 5,
    date: "2016-05-08",
    name: "王小虎555",
    age: 25,
    address: "上海市普陀区金沙江路 1518 弄",
  },
]);

onMounted(() => {
  columnDrop();
});

/**
 * 列拖拽排序
 */
function columnDrop() {
  // 要侦听拖拽响应的DOM对象
  const wrapperTr = document.querySelector(".el-table__header-wrapper tr");
  Sortable.create(wrapperTr, {
    animation: 180,
    delay: 0,
    onEnd({ newIndex, oldIndex }) {
      const draggedItem = columns.value.splice(oldIndex, 1)[0];
      columns.value.splice(newIndex, 0, draggedItem);
    },
  });
}
</script>

<template>
  <el-table
    ref="table"
    :data="tableData"
    style="width: 100%"
    border
    row-key="id"
  >
    <el-table-column
      v-for="(column, index) in columns"
      :key="index"
      :prop="column.prop"
      :label="column.label"
    />
  </el-table>
</template>

禁止某几行拖拽

效果
在这里插入图片描述

<script setup>
import { onMounted, ref } from "vue";
import Sortable from "sortablejs";

const columns = ref([
  { label: "日期", prop: "date" },
  { label: "姓名", prop: "name", draggable: true },
  { label: "年龄", prop: "age", draggable: true },
  { label: "地址", prop: "address" },
]);

const columnsDrop = ref([
  { label: "日期", prop: "date" },
  { label: "姓名", prop: "name" },
  { label: "年龄", prop: "age" },
  { label: "地址", prop: "address" },
]);

const tableData = ref([
  {
    id: 1,
    date: "2016-05-02",
    name: "王小虎111",
    age: 21,
    address: "上海市普陀区金沙江路 1518 弄",
  },
  {
    id: 2,
    date: "2016-05-04",
    name: "王小虎222",
    age: 22,
    address: "上海市普陀区金沙江路 1517 弄",
  },
  {
    id: 3,
    date: "2016-05-01",
    name: "王小虎333",
    age: 23,
    address: "上海市普陀区金沙江路 1519 弄",
  },
  {
    id: 4,
    date: "2016-05-03",
    name: "王小虎444",
    age: 24,
    address: "上海市普陀区金沙江路 1516 弄",
  },
  {
    id: 5,
    date: "2016-05-08",
    name: "王小虎555",
    age: 25,
    address: "上海市普陀区金沙江路 1518 弄",
  },
]);

// 定义变量来记录固定列的class名
const fixedColumnClass = "filtered";

onMounted(() => {
  columnDrop();
});

function setHeaderCellClass({ column }) {
  const columnLabels = columns.value
    .filter((column) => column.draggable)
    .map((column) => column.label);
  return !columnLabels.includes(column.label) ? fixedColumnClass : "";
}

/**
 * 列拖拽排序
 */
function columnDrop() {
  // 要侦听拖拽响应的DOM对象
  const wrapperTr = document.querySelector(".el-table__header-wrapper tr");
  Sortable.create(wrapperTr, {
    animation: 180,
    delay: 0,
    ghostClass: "target-row-class",
    filter: `.${fixedColumnClass}`,
    // filter: (event, item) => {
    //   // 也可以根据item的类名、id或其他属性来决定是否应该被排除
    //   return !item.classList.contains("draggable");
    // },
    onMove: function ({ related }) {
      return related.className.indexOf(fixedColumnClass) === -1;
    },
    onEnd({ newIndex, oldIndex }) {
      const draggedItem = columnsDrop.value.splice(oldIndex, 1)[0];
      columnsDrop.value.splice(newIndex, 0, draggedItem);
    },
  });
}
</script>

<template>
  <el-table
    ref="table"
    :data="tableData"
    style="width: 100%"
    border
    row-key="id"
    :header-cell-class-name="setHeaderCellClass"
  >
    <el-table-column
      v-for="(column, index) in columns"
      :key="column.prop"
      :prop="columnsDrop[index].prop"
      :label="column.label"
    />
  </el-table>
</template>

<style scoped lang="less">
.el-table {
  ::v-deep {
    .target-row-class {
      background: #f0f9eb;
    }

    .filtered {
      background-color: #1db1e7 !important;
    }
  }
}
</style>

封装Vue指令

未完待续

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1440143.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Flink流式数据倾斜

1. 流式数据倾斜 流式处理的数据倾斜和 Spark 的离线或者微批处理都是某一个 SubTask 数据过多这种数据不均匀导致的&#xff0c;但是因为流式处理的特性其中又有些许不同 2. 如何解决 2.1 窗口有界流倾斜 窗口操作类似Spark的微批处理&#xff0c;直接两阶段聚合的方式来解决…

【stm32】hal库学习笔记-ADC模数转换(超详细)

【stm32】hal库学习笔记-ADC模数转换&#xff08;超详细&#xff09; 本篇章介绍了ADC实现电压检测的三种方式 ADC原理及选型 ADC将连续的模拟电压信号转换为二进制的数字信号 选型参数 速度&#xff08;采样频率&#xff09; 功耗 精度 转换原理 ADC hal库驱动函数 普通…

【EEG信号处理】对信号进行模拟生成

生成信号的目的还是主要是为了学习和探究后面的分析方法&#xff1b;本文主要是对方法进行整理 瞬态 transient 瞬态信号是指的是一瞬间信号上去了&#xff0c;这种情况我们可以用在时域上高斯模拟 peaktime 1; % seconds width .12; ampl 9; gaus ampl * exp( -(EEG.tim…

RocketMQ下载安装及基本使用

目录 消息队列的作用 消息队列的优势 应用解耦 异步提速 削峰填谷 RocketMQ介绍 RocketMQ特点 RocketMQ安装下载(4.9.5版本) RocketMQ启动可视化管理服务 RocketMQ实现基本消息收发 消息队列的作用 队列是一种FIFO先进先出的数据结构。消息则是跨进程传递的数据。一个…

多线程JUC:多线程的实现和常用成员方法(守护、礼让、插入线程)

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位大四、研0学生&#xff0c;正在努力准备大四暑假的实习 &#x1f30c;上期文章&#xff1a;首期文章 &#x1f4da;订阅专栏&#xff1a;多线程&JUC 希望文章对你们有所帮助 JUC的学习也是需要一些计算机、操作系统的…

【算法设计与分析】求根节点到叶节点数字之和

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;算法分析与设计 ⛺️稳中求进&#xff0c;晒太阳 题目 给你一个二叉树的根节点 root &#xff0c;树中每个节点都存放有一个 0 到 9 之间的数字。 每条从根节点到叶节点的路径都代表一个数…

高可用 k8s 1.29 一键安装脚本, 丝滑至极

博客原文 文章目录 集群配置配置清单集群规划集群网络规划 环境初始化主机配置 配置高可用ApiServer安装 nginx安装 Keepalived 安装脚本需要魔法的脚本不需要魔法的脚本配置自动补全加入其余节点 验证集群 集群配置 配置清单 OS&#xff1a; ubuntu 20.04kubernetes&#xf…

HarmonyOS class类对象基础使用

按我们之前的写法 就是 Entry Component struct Dom {p:Object {name: "小猫猫",age: 21,gf: {name: "小小猫猫",age: 18,}}build() {Row() {Column() {// ts-ignoreText(this.p.gf.name)}.width(100%)}.height(100%)} }直接用 Object 一层一层往里套 这…

MySQL用心总结

大家好&#xff0c;好久不见&#xff0c;今天笔者用心一步步写一份mysql的基础操作指南&#xff0c;欢迎各位点赞收藏 -- 启动MySQL net start mysql-- 创建Windows服务 sc create mysql binPath mysqld_bin_path(注意&#xff1a;等号与值之间有空格) mysql -h 地址 -…

【Flink状态管理(二)各状态初始化入口】状态初始化流程详解与源码剖析

文章目录 1. 状态初始化总流程梳理2.创建StreamOperatorStateContext3. StateInitializationContext的接口设计。4. 状态初始化举例&#xff1a;UDF状态初始化 在TaskManager中启动Task线程后&#xff0c;会调用StreamTask.invoke()方法触发当前Task中算子的执行&#xff0c;在…

如何从 iPhone 上恢复永久删除的照片

您的 iPhone 上缺少照片吗&#xff1f;讽刺的是&#xff0c;iPhone 的许多高级功能可能正是这个问题如此普遍的原因。幸运的是&#xff0c;还有很多方法可以从 iPhone 恢复已删除的照片&#xff0c;具体取决于您设备的设置方式。 本文涵盖了所有这些内容。该过程根据您的具体情…

git安装配置

1、下载安装 下载地址 2、配置git用户 git config --global user.name "yw" git config --global user.email "88888qq.com" 3、git init 初始化 4、生成ssh密钥 mkdir .ssh //创建文件夹cd .ssh //进入新建文件夹 ssh-keygen -t rsa // 输入密钥文…

计算机服务器中了halo勒索病毒如何处理,halo勒索病毒解密数据恢复

网络技术的不断发展与应用&#xff0c;为企业的生产生活提供了极大便利&#xff0c;但网络数据安全威胁无处不在&#xff0c;近日&#xff0c;云天数据恢复中心接到某连锁超市求助&#xff0c;企业计算机服务器被halo勒索病毒攻击&#xff0c;导致计算机系统瘫痪&#xff0c;无…

将xyz格式的GRACE数据转成geotiff格式

我们需要将xyz格式的文件转成geotiff便于成图&#xff0c;或者geotiff转成xyz用于数据运算&#xff0c;下面介绍如何实现这一操作&#xff0c;采用GMT和matlab两种方法。 1.GMT转换 我们先准备一个xyz文件&#xff0c;这里是一个降水文件。在gmt中采用以下的语句实现xyz转grd…

【Spring】GoF 之工厂模式

一、GoF 23 设计模式简介 设计模式&#xff1a;一种可以被重复利用的解决方案 GoF&#xff08;Gang of Four&#xff09;&#xff0c;中文名——四人组 《Design Patterns: Elements of Reusable Object-Oriented Software》&#xff08;即《设计模式》一书&#xff09;&…

TCP 传输控制协议

1 TCP 1.1 TCP 最主要的特点 1.TCP 是面向连接的运输层协议。 2.每一条 TCP 连接只能有两个端点 (endpoint)&#xff0c;每一条 TCP 连接只能是点对点的&#xff08;一对一&#xff09;。 3.TCP 提供可靠交付的服务。 4.TCP 提供全双工通信。 5.面向字节流 TCP 中的“流…

【Qt】Android上运行keeps stopping, Desktop上正常

文章目录 问题 & 背景背景问题 解决方案One More ThingTake Away 问题 & 背景 背景 在文章【Qt】最详细教程&#xff0c;如何从零配置Qt Android安卓环境中&#xff0c;我们在Qt中配置了安卓开发环境&#xff0c;并且能够正常运行。 但笔者在成功配置并完成上述文章…

Git、github与gitee码云

1.git核心是两个仓库&#xff1a;本地仓库和远程仓库 主要用于团队合作和代码版本控制&#xff08;个人现有版本代码出错可回溯上个提交版本的代码&#xff09; 远程仓库国际主流githut&#xff0c;但外网速度问题&#xff0c;国内可使用码云gitee github&#xff1a;https:…

Springboot拦截器中跨域失效的问题、同一个接口传入参数不同,一个成功,一个有跨域问题、拦截器和@CrossOrigin和@Controller

Springboot拦截器中跨域失效的问题 一、概述 1、具体场景 起因&#xff1a; 同一个接口&#xff0c;传入不同参数进行值的修改时&#xff0c;一个成功&#xff0c;另一个竟然失败&#xff0c;而且是跨域问题拦截器内的request参数调用getHeader方法时&#xff0c;获取不到前端…

CSS:九宫格布局

九宫格布局效果如下&#xff1a; HTML 结构&#xff1a; <div class"container"><div class"item">1</div><div class"item">2</div><div class"item">3</div><div class"item&q…