当前位置: 首页 > news >正文

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

实现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-tableref="table":data="tableData"style="width: 100%"borderrow-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-tableref="table":data="tableData"style="width: 100%"borderrow-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-tableref="table":data="tableData"style="width: 100%"borderrow-key="id"><el-table-columnv-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-tableref="table":data="tableData"style="width: 100%"borderrow-key="id":header-cell-class-name="setHeaderCellClass"><el-table-columnv-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指令

未完待续

相关文章:

  • SQL世界之命令语句Ⅲ
  • C语言--------指针(1)
  • [技术杂谈]如何下载vscode历史版本
  • 使用Pillow来生成简单的红包封面
  • freertos 源码分析五 任务调度一
  • 时光峰峦文物璀璨,预防性保护筑安全
  • 鸿蒙4.0.0 安装minitouch
  • 优雅的从HuggingFace下载模型
  • 【算法与数据结构】583、72、LeetCode两个字符串的删除操作+编辑距离
  • Python HTTP隧道在远程通信中的应用:穿越网络的“魔法门”
  • VRRP协议详解
  • Rust开发WASM,浏览器运行WASM
  • CSS:三列布局
  • C++设计模式-简单工厂模式,工厂方法模式,抽象工厂模式
  • HarmonyOS 鸿蒙应用开发(十、第三方开源js库移植适配指南)
  • 【5+】跨webview多页面 触发事件(二)
  • 【跃迁之路】【477天】刻意练习系列236(2018.05.28)
  • 07.Android之多媒体问题
  • express如何解决request entity too large问题
  • HTTP传输编码增加了传输量,只为解决这一个问题 | 实用 HTTP
  • HTTP中的ETag在移动客户端的应用
  • iOS小技巧之UIImagePickerController实现头像选择
  • js数组之filter
  • Redux 中间件分析
  • Vue小说阅读器(仿追书神器)
  • 如何设计一个比特币钱包服务
  • 优秀架构师必须掌握的架构思维
  • Semaphore
  • 阿里云移动端播放器高级功能介绍
  • 浅谈sql中的in与not in,exists与not exists的区别
  • (1)(1.13) SiK无线电高级配置(六)
  • (2)Java 简介
  • (c语言)strcpy函数用法
  • (附源码)小程序儿童艺术培训机构教育管理小程序 毕业设计 201740
  • (十二)springboot实战——SSE服务推送事件案例实现
  • (十七)Flask之大型项目目录结构示例【二扣蓝图】
  • (转)Android中使用ormlite实现持久化(一)--HelloOrmLite
  • (转)Mysql的优化设置
  • ***php进行支付宝开发中return_url和notify_url的区别分析
  • ./configure,make,make install的作用
  • .aanva
  • .net core使用ef 6
  • .net websocket 获取http登录的用户_如何解密浏览器的登录密码?获取浏览器内用户信息?...
  • .net 托管代码与非托管代码
  • .NET/MSBuild 中的发布路径在哪里呢?如何在扩展编译的时候修改发布路径中的文件呢?
  • .Net调用Java编写的WebServices返回值为Null的解决方法(SoapUI工具测试有返回值)
  • .net实现头像缩放截取功能 -----转载自accp教程网
  • @hook扩展分析
  • @RestControllerAdvice异常统一处理类失效原因
  • [AIGC] 如何建立和优化你的工作流?
  • [ArcPy百科]第三节: Geometry信息中的空间参考解析
  • [Asp.net MVC]Bundle合并,压缩js、css文件
  • [C#]获取指定文件夹下的所有文件名(递归)
  • [CF482B]Interesting Array
  • [docker] Docker的私有仓库部署——Harbor