el-transfer和el-tree进行结合搞一个树形穿梭框

由于业务需求需要在穿梭框里使用树形结构,但是本身element里并不支持,于是参考了别的大佬发的文章作为思路及后续自己新增了一些处理功能。
目录
1.拷贝代码放到自己的项目目录中
2.改造el-transfer的源码
3.修改tree-transfer-panel.vue文件
4.修改index.vue文件
5.对tree-transfer-panel.vue文件功能进行完善
1.拷贝代码放到自己的项目目录中
在github上搜索element,拷贝packages/transfer/src中的vue文件,放到项目的components/tree-transfer目录。把main.vue改成index.vue方便操作。

在需要用到穿梭框的页面中拷贝transfer源码的组件,效果和使用el-transfer效果一致
<my-el-tree-transferv-model="treeChecked":data="treeData":titles="['请选择功能', '已选择功能']"@change="transferChange"target-order='push'>
</my-el-tree-transfer>
...
import myElTreeTransfer from '@/components/treeTransfer'
export default {data(){// 初始的数据源functionSourceArray: [{ key: 1, label: '功能1' },{ key: 2, label: '功能2' },{ key: 3, label: '功能3' },{ key: 4, label: '功能4' },],treeChecked: [],// 改造后数据源需要tree结构的数据treeData: [{label: '一级 1', children: [{ key: 2, label: '二级 1-1' },{ key: 3, label: '二级 1-2' },]},{label: '一级 2', children: [{ key: 5, label: '二级 2-1' },{ key: 6, label: '二级 2-2' },]},]}
}
2.改造el-transfer的源码
index.vue的dom由三部分组成,左边的panel、中间的操作按钮,右边的panel,只需要修改左边的panel就可以,接下来拷贝一份transfer-panel.vue并改名为tree-transfer-panel.vue,修改index.vue的引用
// index.vue
<div class="el-transfer"><tree-transfer-panel ...></tree-transfer-panel><div class="el-transfer__buttons">...</div><transfer-panel ...></transfer-panel>
</div>
...
import TreeTransferPanel from './tree-transfer-panel.vue';
3.修改tree-transfer-panel.vue文件
先将中间部分的checked-group替换为el-tree
// tree-transfer-panel.vue
<div :class="['el-transfer-panel__body', hasFooter ? 'is-with-footer' : '']"><el-input class="el-transfer-panel__filter" v-model="query" size="small" :placeholder="placeholder"@mouseenter.native="inputHover = true" @mouseleave.native="inputHover = false" v-if="filterable"><i slot="prefix" :class="['el-input__icon', 'el-icon-' + inputIcon]" @click="clearQuery"></i></el-input><!-- 原先的el-checkbox-group --><!-- <el-checkbox-group v-model="checked" v-show="!hasNoMatch && data.length > 0":class="{ 'is-filterable': filterable }" class="el-transfer-panel__list"><el-checkbox class="el-transfer-panel__item" :label="item[keyProp]" :disabled="item[disabledProp]":key="item[keyProp]" v-for="item in filteredData"><option-content :option="item"></option-content></el-checkbox></el-checkbox-group> --><!-- 替换后的el-tree --><el-tree ref="tree" :data="filteredData" node-key="key" default-expand-all show-checkbox :default-checked-keys="checked" @check="treeCheckChange"></el-tree><p class="el-transfer-panel__empty" v-show="hasNoMatch">{{ t('el.transfer.noMatch') }}</p><p class="el-transfer-panel__empty" v-show="data.length === 0 && !hasNoMatch">{{ t('el.transfer.noData') }}</p>
</div>
添加el-tree选择的event
@check 当复选框被点击的时候触发 共两个参数,依次为:传递给 data 属性的数组中该节点所对应的对象、树目前的选中状态对象,包含 checkedNodes、checkedKeys、halfCheckedNodes、halfCheckedKeys 四个属性
checkedKeys选中的key
halfCheckedKeys半选中的key
这时候看页面,结构已经出来了
treeCheckChange(cur,checkedInfo){const {checkedKeys} = checkedInfothis.checked = checkedKeys
}
4.修改index.vue文件
先把dom结构的第一个panel换为tree-transfer-panel.vue
<div class="el-transfer"><tree-transfer-panel ...
左边的panel及右边的panel:data数据都是计算属性,右边的结构没有改变,左边的结构变为了tree,所以只需要把左边的:data改变即可。原来的数据结构是一维数组,现在的是二维数组,数据源需要根据数据结构做相应的改变。
这个sourceData作用是每次把左边的数据添加到右边以后需要把添加的数据从左边去掉。
// index.vue
sourceData() {let temp = []const originalData = this.datafor(let i=0; i<originalData.length;i++){temp.push({label: originalData[i].label})temp[i].children = []for(let j=0; j<originalData[i].children.length; j++){let tempKey = originalData[i].children[j].keyif(this.value.indexOf(tempKey) === -1){temp[i].children.push(originalData[i].children[j])}}}return temp// return this.data.filter(item => this.value.indexOf(item[this.props.key]) === -1);
},
修改完以后每次往右边添加左边的该数据就会消失。但是此时右边并没有显示出左边添加过去的数据,此时需要修改addToRight方法
addToRight() {let currentValue = this.value.slice();const itemsToBeMoved = [];const key = this.props.key;let dataTemp = []// 该处是修改部分,数据结构变为二维以后,需要把第二层的数据放到数据源中this.data.forEach(item=>{dataTemp = dataTemp.concat(item.children)})dataTemp.forEach(item => {const itemKey = item[key];if (this.leftChecked.indexOf(itemKey) > -1 &&this.value.indexOf(itemKey) === -1) {itemsToBeMoved.push(itemKey);}});currentValue = this.targetOrder === 'unshift'? itemsToBeMoved.concat(currentValue): currentValue.concat(itemsToBeMoved);this.$emit('input', currentValue);this.$emit('change', currentValue, 'right', this.leftChecked);
},
右边panel展示的数据computed由于用到的dataObj,所以计算属性dataObj也要做相应调整
dataObj() {const key = this.props.key;let temp = []// 获取第二层的数据this.data.forEach(item=>{temp = temp.concat(item.children)})return temp.reduce((o, cur) => (o[cur[key]] = cur) && o, {});// return this.data.reduce((o, cur) => (o[cur[key]] = cur) && o, {});
},
这时候正常结构和功能都已经出来了,那么接下来我又新增了全选及当没有子节点的情况下禁止选中的功能。
5.对tree-transfer-panel.vue文件功能进行完善
对复选框点击事件进行修改,可以对树级选择器进行全选及取消操作
//tree-transfer-panel.vue<p class="el-transfer-panel__header"><el-checkbox v-model="allChecked" @change="handleAllCheckedChange" :indeterminate="isIndeterminate">{{ title }}<span>{{ checkedSummary }}</span></el-checkbox></p>handleAllCheckedChange(isChecked) {// this.checked = value// ? this.checkableData.map(item => item[this.keyProp])// : [];const allKeys = this.filteredData.reduce((acc, node) => {acc.push(node.key);if (node.children) {acc.push(...this.getAllKeys(node.children));}return acc;}, []);this.checked = isChecked ? allKeys : [];this.$refs.tree.setCheckedKeys(this.checked);},getAllKeys(nodes) {return nodes.reduce((acc, node) => {acc.push(node.key);if (node.children) {acc.push(...this.getAllKeys(node.children));}return acc;}, []);},
对于没有子节点的父级进行禁止选中功能,通过监听树级结构data里的数据,来给父节点是否增加disabled禁止选中
<el-tree ref="tree" :data="filteredData" node-key="key" show-checkbox:class="{ 'is-filterable': filterable }" class="el-transfer-panel__list ":default-checked-keys="checked" @check="treeCheckChange">
</el-tree>watch:{filteredData(newVal) {this.disableNodesWithoutChildren(newVal);},
},
methods:{disableNodesWithoutChildren(nodes) {nodes.forEach((node) => {if (node.children && node.children.length === 0) {node.disabled = true; // 如果没有子节点,禁用该节点} else if (node.children) {// 如果有子节点,递归处理子节点this.disableNodesWithoutChildren(node.children);}});},
}
这样所有功能都已经完成。在把树级结构的数据替换成自己的后端接口返回的数据及就可以了。
需要注意一点,我自己引进的时候由于我使用的是vue2语法,有一处地方提示我使用了jsx语法而报错

于是我改变了它形式,具体功能和展示效果与原来一样

最后我自己的效果展示

参考文章 https://juejin.cn/post/7066079104742719525?searchId=20240522133658C46B56C6941369684F86
github地址 GitHub - ElemeFE/element: A Vue.js 2.0 UI Toolkit for Web
相关文章:
el-transfer和el-tree进行结合搞一个树形穿梭框
由于业务需求需要在穿梭框里使用树形结构,但是本身element里并不支持,于是参考了别的大佬发的文章作为思路及后续自己新增了一些处理功能。 目录 1.拷贝代码放到自己的项目目录中 2.改造el-transfer的源码 3.修改tree-transfer-panel.vue文件 4.修改…...
编一个自己的万年历
编一个自己的万年历 前阶段突然想查一下某一天是星期几,于是自己编了一个[小程序][https://blog.csdn.net/weixin_41905135/article/details/138972055?spm1001.2014.3001.5501],但是功能很单一,就是单纯的查是星期几。(虽然用网…...
Golang gin框架中间件c.JSON返回结果后终止返回
gin框架中间件c.JSON返回结果后还是会继续执行之后的方法,我们可以用c.Abort()来终止后续的处理 func MiddlewareFunction(c *gin.Context) {// 假设有某种条件下需要返回错误if someCondition {c.JSON(http.StatusBadRequest, gin.H{"error": "som…...
码蹄集部分题目(2024OJ赛16期;单调栈集训+差分集训)
🧀🧀🧀单调栈集训 🥪单调栈 单调递增栈伪代码: stack<int> st; for(遍历数组) {while(栈不为空&&栈顶元素大于当前元素)//单调递减栈就是把后方判断条件变为小于等于即可{栈顶元素出栈;//同时进行其他…...
安卓玩机搞机技巧综合资源----自己手机制作证件照的几种方法 免费制作证件照
接上篇 安卓玩机搞机技巧综合资源------如何提取手机分区 小米机型代码分享等等 【一】 安卓玩机搞机技巧综合资源------开机英文提示解决dm-verity corruption your device is corrupt. 设备内部报错 AB分区等等【二】 安卓玩机搞机技巧综合资源------EROFS分区格式 小米红…...
揭秘循环购模式:消费返利新玩法,引领电商新潮流
在当今的消费市场中,有一种商业模式引起了广大消费者的热烈讨论——那就是循环购模式。你可能会想,消费满千元就能得到两千元的福利,每天还能领取现金,这怎么可能呢?商家难道真的在“慷慨解囊”?今天&#…...
【制作100个unity游戏之26】unity2d横版卷轴动作类游13(附带项目源码)
最终效果 系列导航 文章目录 最终效果系列导航前言存储点灯光后处理存储位置信息存储更多数据存储场景信息持久化存储数据引入Unity 的可序列化字典类调用 游戏结束源码完结 前言 欢迎来到【制作100个Unity游戏】系列!本系列将引导您一步步学习如何使用Unity开发各…...
Golang使用HTTP框架zdpgo_resty实现文件下载
核心代码 代码解析: client.SetOutputDirectory("Downloads") 设置下载目录client.R().SetOutput("test.go").Get("http://127.0.0.1:3333/download 指定下载文件名并进行下载 // 设置输出目录路径,如果目录不存在ÿ…...
提取COCO 数据集的部分类
1.python提取COCO数据集中特定的类 安装pycocotools github地址:https://github.com/philferriere/cocoapi pip install githttps://github.com/philferriere/cocoapi.git#subdirectoryPythonAPI若报错,pip install githttps://github.com/philferriere…...
高刚性滚柱直线导轨有哪些优势?
滚柱导轨是机械传动系统中用于支持和引导滑块或导轨的装置,承载能力较高、刚性强及高精度等特点。特别适用于大负载和高刚性的工业设备,如机床、数控机床等设备,这些优势使其在工业生产和机械设备中得到了广泛的应用。 1、高精度:…...
KNN及降维预处理方法LDA|PCA|MDS
文章目录 基本原理模型介绍模型分析 python代码实现降维处理维数灾难 curse of dimensionality线性变换 Linear TransformationLDA - 线性判别分析LDA python 实现PCA - 主成分分析PCA最近重构性PCA最大可分性PCA求解及说明PCA python实现 多维缩放 Multiple Dimensional Scali…...
论文精读-SwinIR Image Restoration Using Swin Transformer
论文精读-SwinIR: Image Restoration Using Swin Transformer SwinIR:使用 Swin Transformer进行图像恢复 参数量:SR 11.8M、JPEG压缩伪影 11.5M、去噪 12.0M 优点:1、提出了新的网络结构。它采用分块设计。包括浅层特征提取:cnn提取&#…...
解释Spring Bean的生命周期
Spring Bean的生命周期涉及到Bean的创建、配置、使用和销毁的各个阶段。理解这个生命周期对于编写高效的Spring应用和充分利用框架的功能非常重要。下面是Spring Bean生命周期的主要步骤: 1. 实例化Bean Spring容器首先将使用Bean的定义(无论是XML、注…...
CTF网络安全大赛web题目:字符?正则?
题目来源于:bugku 题目难度:难 题目描 述: 字符?正则? 题目htmnl源代码: <code><span style"color: #000000"> <span style"color: #0000BB"><?php <br />highl…...
Linux——Docker容器虚拟化平台
安装docker 安装 Docker | Docker 从入门到实践https://vuepress.mirror.docker-practice.com/install/ 不需要设置防火墙 docker命令说明 docker images #查看所有本地主机的镜像 docker search 镜像名 #搜索镜像 docker pull 镜像名 [标签] #下载镜像&…...
Transformer详解(3)-多头自注意力机制
attention multi-head attention pytorch代码实现 import math import torch from torch import nn import torch.nn.functional as Fclass MultiHeadAttention(nn.Module):def __init__(self, heads8, d_model128, droput0.1):super().__init__()self.d_model d_model # 12…...
运用HTML、CSS设计Web网页——“西式甜品网”图例及代码
目录 一、效果展示图 二、设计分析 1.整体效果分析 2.头部header模块效果分析 3.导航及banner模块效果分析 4.分类classify模块效果分析 5.产品展示show模块效果分析 6.版权banquan模块效果分析 三、HTML、CSS代码分模块展示 1. 头部header模块代码 2.导航及bann…...
大语言模型是通用人工智能的实现路径吗?【文末有福利】
相关说明 这篇文章的大部分内容参考自我的新书《解构大语言模型:从线性回归到通用人工智能》,欢迎有兴趣的读者多多支持。 关于大语言模型的内容,推荐参考这个专栏。 内容大纲 相关说明一、哲学与人工智能二、内容简介三、书籍简介与福利粉…...
c语言——宏offsetof
1.介绍 !!! offsetof 是一个宏 2.使用举例 结构体章节的计算结构体占多少字节需要先掌握(本人博客结构体篇章中已经讲解过) 计算结构体中某变量相对于首地址的偏移,并给出说明 首先,结构体首个…...
C#串口通信-串口相关参数介绍
串口通讯(Serial Communication),是指外设和计算机间,通过数据信号线、地线等,按位进行传输数据的一种双向通讯方式。 串口是一种接口标准,它规定了接口的电气标准,没有规定接口插件电缆以及使用的通信协议,…...
【Python】 -- 趣味代码 - 小恐龙游戏
文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...
云计算——弹性云计算器(ECS)
弹性云服务器:ECS 概述 云计算重构了ICT系统,云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台,包含如下主要概念。 ECS(Elastic Cloud Server):即弹性云服务器,是云计算…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...
K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...
【位运算】消失的两个数字(hard)
消失的两个数字(hard) 题⽬描述:解法(位运算):Java 算法代码:更简便代码 题⽬链接:⾯试题 17.19. 消失的两个数字 题⽬描述: 给定⼀个数组,包含从 1 到 N 所有…...
Golang dig框架与GraphQL的完美结合
将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...
微信小程序 - 手机震动
一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注:文档 https://developers.weixin.qq…...
EtherNet/IP转DeviceNet协议网关详解
一,设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络,本网关连接到EtherNet/IP总线中做为从站使用,连接到DeviceNet总线中做为从站使用。 在自动…...
HTML前端开发:JavaScript 常用事件详解
作为前端开发的核心,JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例: 1. onclick - 点击事件 当元素被单击时触发(左键点击) button.onclick function() {alert("按钮被点击了!&…...
聊一聊接口测试的意义有哪些?
目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...
