vue2 element el-transfer穿梭框组件支持拖拽及排序 已封装,随取随用

项目场景:

项目中有个功能用到穿梭框组件,新版本需要支持穿梭框组件排序,由于element2版本中的穿梭框组件本身不支持排序功能

在此不仅需要支持随意更换顺序,还支持从一侧拖拽至另一侧,具体功能效果图如下:
在这里插入图片描述
啊啊啊对不住哈哈,GIF过于模糊,自行脑补吧,临时没找到免费的视频转GIF


穿梭框组件封装代码如下

提示:关于拖拽部分代码是基于其他大佬的基础上稍作修改,原博文地址:[https://blog.csdn.net/juvenile_Li/article/details/126886010?spm=1001.2014.3001.5506]

Tips1: 此功能使用到了sortablejs插件,请务必先下载本插件再引用下面的代码,sortablejs安装命令为:npm install sortablejs --save

Tips2: 下面的代码中引入的其他方法请自行根据自己的项目进行修改,比如:错误提示Messagebox

//先看封装好的组件,此处我们是加了弹框的,如果不需要自行修改去掉即可
<template><div class="delete-info-dialog"><el-dialog:title="dialogTitle":visible.sync="tableItemDialogVisible":close-on-click-modal="false":close-on-press-escape="false"width="700px":before-close="handleClose"><div class="info-body"><el-transfer ref="transfer"v-model="visibleValue":data="transferData":titles="transferTitle"target-order="push":props="transferProps"@left-check-change="leftCheckChange"@right-check-change="rightCheckChange"><span slot-scope="{ option }"draggable="!option.disabled"@dragstart="drag($event, option)">{{ option.label }}</span></el-transfer></div><span slot="footer" class="dialog-footer"><el-button type="primary" @click="handleConfirm">确 定</el-button></span></el-dialog></div>
</template><script>
import Sortable from 'sortablejs' //记得安装拖拽组件哦
import cloneDeep from "lodash.clonedeep"; //这个是深拷贝方法,也可以换成自己的,也可以下载lodash,此处为了避免修改父组件传过来的数据
export default {name: "visible-item-table-dialog",props: {//此处是可以随意定义弹框的文字,且有默认值dialogTitle: {type: String,default: '显示列设置'},//此处是可以定义transfer组件的propstransferProps: {type: Object,default: {key: 'key',label: 'label',}},//此处是可以定义transfer组件的titletransferTitle: {type: Array,default: ()=> ['隐藏列', '显示列']},// 穿梭框总数据transferDataList: {type: Array,default: ()=> []},// 右侧显示列,用户已经选好保存过的数据,从父组件传过来回显visibleTableItemList: {type: Array,default: ()=> []},// 默认显示列,如果用户还没设置过则取这个defaultTableItemList: {type: Array,default: ()=> []},// 控制弹框显隐tableItemDialogVisible: {type: Boolean,default: false},},data() {return {visibleValue: [],//显示列表头数据transferData: [], // 穿梭框数据transferLeftCheckData: [], // 左侧选中数据transferRightCheckData: [], // 右侧选中数据draggingKey: '',  // 当前拖拽项}},mounted() {this.transferData = this.transferDataList;this.visibleValue = this.visibleTableItemList.length>0 ?cloneDeep(this.visibleTableItemList) : cloneDeep(this.defaultTableItemList);// 此处加nextTick 为了保证顺利取到refsthis.$nextTick(()=>{const transfer = this.$refs.transfer.$el;const leftPanel = transfer.getElementsByClassName('el-transfer-panel')[0].getElementsByClassName('el-transfer-panel__body')[0]const rightPanel = transfer.getElementsByClassName('el-transfer-panel')[1].getElementsByClassName('el-transfer-panel__body')[0]const rightEl = rightPanel.getElementsByClassName('el-transfer-panel__list')[0]Sortable.create(rightEl, {onEnd: evt => {const { oldIndex, newIndex } = evtconst temp = this.visibleValue[oldIndex]if (!temp || temp === 'undefined') {return} // 解决右边最后一项从右边拖左边,有undefined的问题// this.$set(this.visibleValue, oldIndex, this.visibleValue[newIndex]) //这种赋值方法会导致数据更新视图未更新,排序后顺序展示错乱,强制更新也无效,原博主是这么赋值的,仅供参考// this.$set(this.visibleValue, newIndex, temp)let _arr = this.visibleValue.splice(oldIndex, 1)this.visibleValue.splice(newIndex, 0, _arr[0])}})// 目前只让右侧支持拖拽顺序即可,左侧暂时注释const leftEl = leftPanel.getElementsByClassName('el-transfer-panel__list')[0]Sortable.create(leftEl, {onEnd: evt => {const { oldIndex, newIndex } = evtconst temp = this.transferData[oldIndex]if (!temp || temp === 'undefined') {return} // 解决右边最后一项从左边拖右边,有undefined的问题            let _arr = this.transferData.splice(oldIndex, 1)this.transferData.splice(newIndex, 0, _arr[0])}})// 关于左侧拖拽至右侧的功能,在本项目中暂时无法实现,经检测drag事件未触发(除了本项目外都可),后续再研究^_^leftPanel.ondragover = ev => ev.preventDefault()leftPanel.ondrop = ev => {ev.preventDefault()// 往左拉const index = this.visibleValue.indexOf(this.draggingKey)if (index !== -1) {// 如果当前拉取的是选中数据就将所有选中的数据拉到左边选中框内if (this.transferRightCheckData.indexOf(this.draggingKey) !== -1) {// 此处为多选执行this.transferRightCheckData.reduce((arr, item) => {if (arr.indexOf(item) !== -1) {// 每次计算将相同的删掉arr.splice(arr.indexOf(item), 1)}return arr}, this.visibleValue)this.transferRightCheckData = []// 清除右侧选中的 不然下次向左拉取时会有缓存// 否则就只拉取当前一个} else {this.visibleValue.splice(index, 1)}}}rightPanel.ondragover = ev => ev.preventDefault()rightPanel.ondrop = ev => {ev.preventDefault()if (!this.draggingKey || this.draggingKey === 'undefined') {return} // 解决右边最后一项从左边拖右边,有undefined的问题// 右边框里没有当前key值的时候 向右拉if (this.visibleValue.indexOf(this.draggingKey) === -1) {// 此处为多选执行// 如果当前拉取的是选中数据就将所有选中的数据拉到右边选中框内if (this.transferLeftCheckData.indexOf(this.draggingKey) !== -1) {this.visibleValue =this.visibleValue.concat(this.transferLeftCheckData)this.transferLeftCheckData = [] // 清除左侧选中的  不然下次向右拉取时会有缓存} else {// 否则就只拉取当前一个this.visibleValue.push(this.draggingKey)}}}})},methods: {//关闭弹框handleClose(){this.$emit("handleCloseTableItem");},//点击确定按钮handleConfirm(){if(this.visibleValue.length<=0){this.$message({message: '未选中任何需要显示的数据',type: 'warning'});return;}this.$emit("handleConfirmVisible",this.visibleValue)},drag(ev, option) {// 赋值当前拖拽的唯一标识this.draggingKey = option[this.transferProps.key]},leftCheckChange(val) {// 穿梭框左侧多选选中this.transferLeftCheckData = [...val]},rightCheckChange(val) {// 穿梭框右侧多选选中this.transferRightCheckData = [...val]},},
}
</script><style lang="scss" scoped>
.delete-info-dialog{/deep/ .el-dialog__body{max-height: 400px;overflow-y: auto;}.info-body{color: #909399;padding-top: 20px;padding-bottom: 20px;.success-info{height: 20px;line-height: 20px;}.info-list{.info{padding: 0 10px;line-height: 20px;word-break: break-all;}}}
}
</style>

封装组件的应用:

提示:上面的代码是封装好的支持拖拽的穿梭框,且在弹框内哦,不在弹框内的自己修改下吧O(∩_∩)O哈哈~:

第一步:在需要的页面引入封装好的组件
//此处用Button触发弹框打开,不需要弹框的省略
<el-button @click="tableItemDialogVisible= true">打开封装好的穿梭框组件弹框</el-button><visible-dialog:default-table-item-list="defaultTableItemList":table-item-dialog-visible="tableItemDialogVisible"v-if="tableItemDialogVisible":visible-table-item-list="visibleTableItemList":transfer-data-list="transferDataList":transfer-props="{key: 'property',label: 'label',}"@handleCloseTableItem="handleCloseTableItem"@handleConfirmVisible="handleConfirmVisible"></visible-dialog><script>
import VisibleDialog from "../../../components/visible-dialog/index.vue"; //记得修改地址哦,这里引入的就是上面那个封装好的组件,地址务必改为自己的哈,文件名也记得改为自己的哈
export default {   components: {VisibleDialog },data(){return {               tableItemDialogVisible: true,//显隐弹框defaultTableItemList: ['date', 'invoiceClass', 'invoiceCode', 'invoiceNum', 'isTravel'],//如果visibleTableItemList为空,直接取defaultTableItemList的值,这个逻辑可根据自己需要自行修改transferDataList: [{label: '销售方名称', property: 'salename', align:'left', minWidth: 180},{label: '销售方税号', property: 'saleaxpayerid', align:'left', minWidth: 180},{label: '购买方税号', property: 'buytaxnumber', align:'left', minWidth: 180},{label: '发票日期', property: 'date', minWidth: 120,},{label: '发票类型', property: 'invoiceClass', minWidth: 180,},{label: '发票代码', property: 'invoiceCode', minWidth: 180,},{label: '发票号码', property: 'invoiceNum', minWidth: 180,},{label: '是否差旅', property: 'isTravel', minWidth: 120},],visibleTableItemList: [],//这个数组的数据是从后来请求回来的,用户自己设置好顺序的数据,如果没有设置就会去取defaultTableItemList里面的数据,这个demo中咱们就默认为空,假装用户还没设置过哈}},methods: {//  关闭显示列弹框handleCloseTableItem(){this.tableItemDialogVisible = false;},// 点击弹框的确认按钮事件,array就是用户自己放在右侧排好序的数组,handleConfirmVisible(array){console.log("用户选择好的右侧的数据",array)// 这里就可以向后端发送请求,保存用户排好序的数据了},}}
</script>

结语:

提示:按照上述代码复制到自己项目中即可实现顶部GIF中的功能了,如有问题,欢迎留言交流,欢迎大佬指点。

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

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

相关文章

为什么JSX只能在函数的返回语句中使用

JSX只能在函数的返回语句中使用&#xff0c;因为JSX本质上是一种声明式的语法&#xff0c;用于描述React组件的结构和外观。在函数的返回语句中使用JSX&#xff0c;可以将JSX表达式嵌入到组件的输出中。 当我们编写一个React组件时&#xff0c;我们通常需要定义一个Render函数…

消息中间件——RabbitMQ(五)快速入门生产者与消费者,SpringBoot整合RabbitMQ!

前言 本章我们来一次快速入门RabbitMQ——生产者与消费者。需要构建一个生产端与消费端的模型。什么意思呢&#xff1f;我们的生产者发送一条消息&#xff0c;投递到RabbitMQ集群也就是Broker。 我们的消费端进行监听RabbitMQ&#xff0c;当发现队列中有消息后&#xff0c;就进…

森利威尔SL4010 升压恒压 12V升压24V 12V升压36V 12V升压48V

在当今的电子设备中&#xff0c;电源管理系统的设计是非常重要的。为了保证设备的稳定运行&#xff0c;升压和恒压电源的应用已经成为不可或缺的一部分。在这篇文章中&#xff0c;我们将介绍森利威尔SL4010升压恒压电源&#xff0c;它可以实现12V升压24V、12V升压36V、12V升压4…

c 在文本终端中显示yuv图片

把yuv422 转为rgb32 &#xff0c;利用framebuffer 显示 #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdlib.h> #include <unistd.h> #include <sys/ioctl.h> #include <lin…

vue2.6源码分析

vue相关文档 vue-cli官方文档 vuex官方文档 vue-router 官方文档 vue2.6源码地址 如何调试源码 package.json 添加了--sourcemap "scripts": {"dev": "rollup -w -c scripts/config.js --environment TARGET:web-full-dev --sourcemap" }新增…

linux apt update错误提示修复

错误提示&#xff1a; E: Release file for http://security.debian.org/dists/bullseye-security/InRelease is expired (invalid since 15d 14h 45min 26s). Updates for this repository will not be applied. E: Release file for http://ftp.jp.debian.org/debian/dists/b…

【Hello Go】Go语言并发编程

并发编程 概述基本概念go语言的并发优势 goroutinegoroutine是什么创建goroutine如果主goroutine退出runtime包GoschedGoexitGOMAXPROCS channel无缓冲的channel有缓冲的channelrange和close单向channel 定时器TimerTicker Select超时 概述 基本概念 并行和并发概念 并行 &…

CVE-2023-6099:优卡特脸爱云一脸通智慧管理平台SystemMng.ashx接口未授权漏洞复现

文章目录 优卡特脸爱云一脸通智慧管理平台未授权SystemMng.ashx接口漏洞复现&#xff08;CVE-2023-6099&#xff09; [附POC]0x01 前言0x02 漏洞描述0x03 影响版本0x04 漏洞环境0x05 漏洞复现1.访问漏洞环境2.构造POC3.复现 0x06 修复建议 优卡特脸爱云一脸通智慧管理平台未授权…

mysql字符串转为数字的三种方法、字符串转日期

隐式转换 在MySQL中&#xff0c;使用0运算符可以将一个非数字的值隐式地转换为数字。这在进行数学运算或比较操作时非常有用。 需要注意的是&#xff0c;在使用0进行隐式转换时&#xff0c;MySQL会尽可能将字符串转换为数字。如果字符串不能转换为数字&#xff0c;则会返回0。…

【解决】HDFS JournalNode启动慢问题排查

文章目录 一. 问题描述二. 问题分析1. 排查机器性能2. DNS的问题 三. 问题解决 一句话&#xff1a;因为dns的问题导致journalnode启动时很慢&#xff0c;通过修复dns对0.0.0.0域名解析&#xff0c;修复此问题。 一. 问题描述 从journalnode启动到服务可用&#xff0c;完成RPC…

使用Python将图片转换为PDF

将图片转为 PDF 的主要原因之一是为了方便共享和传输。此外&#xff0c;将多张图片合并成一个 PDF 文件还可以简化文件管理。之前文章详细介绍过如何使用第三方库Spire.PDF for Python将PDF文件转为图片&#xff0c;那么本文介绍使用同样工具在Python中实现图片转PDF文件的功能…

【OpenCV+OCR】计算机视觉:识别图像验证码中指定颜色文字

文章目录 1. 写在前面2. 读取验证码图像3. 生成颜色掩码4. 生成黑白结果图5. OCR文字识别6. 测试结果 【作者主页】&#xff1a;吴秋霖 【作者介绍】&#xff1a;Python领域优质创作者、阿里云博客专家、华为云享专家。长期致力于Python与爬虫领域研究与开发工作&#xff01; 【…

Spring Security(安全框架,必须登录成功才能访问指定资源)

一、背景知识 1、Spring Security 是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean&#xff0c;充分利用了Spring IoC&#xff0c;DI&#xff08;IOC: 控制反转Inversion of Control ,DI:D…

24路电磁锁控板的特点和主要参数

智能快递柜、智能生鲜柜、电子存储柜、超市寄存柜、智能送餐柜、电子更衣柜、档案柜等物联网终端设备&#xff0c;都是采用电磁锁控制&#xff0c;这种电磁锁控制板俗称锁控板。锁控板可以远程控制储物柜的开关以及远程监控并提供锁的反馈信号。沐渥开发的24路电磁锁控板可以控…

AI:87-基于深度学习的街景图像地理位置识别

🚀 本文选自专栏:人工智能领域200例教程专栏 从基础到实践,深入学习。无论你是初学者还是经验丰富的老手,对于本专栏案例和项目实践都有参考学习意义。 ✨✨✨ 每一个案例都附带有在本地跑过的代码,详细讲解供大家学习,希望可以帮到大家。欢迎订阅支持,正在不断更新中,…

OpenAI 曾收到 AI 重大突破警告;半独立的 OpenAI 比与微软合并更好丨 RTE 开发者日报 Vol.91

开发者朋友们大家好&#xff1a; 这里是 「RTE 开发者日报」 &#xff0c;每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE &#xff08;Real Time Engagement&#xff09; 领域内「有话题的 新闻 」、「有态度的 观点 」、「有意思的 数据 」、「有思考的 文…

ubuntu下docker环境使用GPU配置

本文主要讲述整个命令流程&#xff0c;具体讲解请看官网nvidia-容器工具包和一篇总结得很详细的博文docker使用GPU总结 docker的版本必须安装19.0版本以上的&#xff0c;这里也只讲19.0版本以上的使用方法 首先设置一下网络信息 curl -fsSL https://nvidia.github.io/libnvi…

LeetCode131. Palindrome Partitioning

文章目录 一、题目二、题解 一、题目 Given a string s, partition s such that every substring of the partition is a palindrome . Return all possible palindrome partitioning of s. Example 1: Input: s “aab” Output: [[“a”,“a”,“b”],[“aa”,“b”]] Exa…

工具【1、计算时间差2、获取当天时间前后七天时间3、根据当前数据的位置,在数组中插入数据4、数组中,某个属性相同的数据放在一块,如把某个日期相同的相连一起】

生成UUID /*** 唯一的随机字符串&#xff0c;用来区分每条数据* returns {string}*/ export function getUid() {return xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx.replace(/[xy]/g, (c) > {const r (Math.random() * 16) | 0;const v c x ? r : (r & 0x3) | 0x8;retu…

【图文详解】SiamFC++与图注意力的强强联合:单目标追踪系统

1.研究背景与意义 随着计算机视觉技术的不断发展&#xff0c;单目标追踪&#xff08;Single Object Tracking, SOT&#xff09;作为计算机视觉领域的一个重要研究方向&#xff0c;已经在许多实际应用中得到了广泛的应用。单目标追踪系统可以通过分析视频序列中的目标运动&…