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),是指外设和计算机间,通过数据信号线、地线等,按位进行传输数据的一种双向通讯方式。 串口是一种接口标准,它规定了接口的电气标准,没有规定接口插件电缆以及使用的通信协议,…...
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...
【JavaEE】-- HTTP
1. HTTP是什么? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议,HTTP是基于TCP协议的一种应用层协议。 应用层协议:是计算机网络协议栈中最高层的协议,它定义了运行在不同主机上…...
PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建
制造业采购供应链管理是企业运营的核心环节,供应链协同管理在供应链上下游企业之间建立紧密的合作关系,通过信息共享、资源整合、业务协同等方式,实现供应链的全面管理和优化,提高供应链的效率和透明度,降低供应链的成…...
Docker 运行 Kafka 带 SASL 认证教程
Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明:server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...
UDP(Echoserver)
网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法:netstat [选项] 功能:查看网络状态 常用选项: n 拒绝显示别名&#…...
屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!
5月28日,中天合创屋面分布式光伏发电项目顺利并网发电,该项目位于内蒙古自治区鄂尔多斯市乌审旗,项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站,总装机容量为9.96MWp。 项目投运后,每年可节约标煤3670…...
spring:实例工厂方法获取bean
spring处理使用静态工厂方法获取bean实例,也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下: 定义实例工厂类(Java代码),定义实例工厂(xml),定义调用实例工厂ÿ…...
AI编程--插件对比分析:CodeRider、GitHub Copilot及其他
AI编程插件对比分析:CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展,AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者,分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...
Java入门学习详细版(一)
大家好,Java 学习是一个系统学习的过程,核心原则就是“理论 实践 坚持”,并且需循序渐进,不可过于着急,本篇文章推出的这份详细入门学习资料将带大家从零基础开始,逐步掌握 Java 的核心概念和编程技能。 …...
IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)
文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...
