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),是指外设和计算机间,通过数据信号线、地线等,按位进行传输数据的一种双向通讯方式。 串口是一种接口标准,它规定了接口的电气标准,没有规定接口插件电缆以及使用的通信协议,…...
Qwen3.5-9B-AWQ-4bit部署教程:Docker容器内路径映射与模型加载权限配置
Qwen3.5-9B-AWQ-4bit部署教程:Docker容器内路径映射与模型加载权限配置 1. 引言 今天我们要探讨的是如何在Docker环境中部署Qwen3.5-9B-AWQ-4bit模型,这是一个支持图像理解的多模态模型。这个模型能够结合上传的图片与文字提示词,输出中文分…...
Android tinyalsa深度解析之pcm_params_get_periods_min调用流程与实战(一百七十三)
简介: CSDN博客专家、《Android系统多媒体进阶实战》作者 博主新书推荐:《Android系统多媒体进阶实战》🚀 Android Audio工程师专栏地址: Audio工程师进阶系列【原创干货持续更新中……】🚀 Android多媒体专栏地址&a…...
Linux环境下Python段错误全解析:从内存管理到线程安全的避坑手册
Linux环境下Python段错误全解析:从内存管理到线程安全的避坑手册 当你在深夜调试一个复杂的Python项目时,突然看到屏幕上跳出"Segmentation fault (core dumped)"的提示,那种感觉就像在高速公路上爆胎——明明代码逻辑看起来没问题…...
Java结构化并发崩溃了?手把手教你用VirtualThread+StructuredTaskScope定位线程泄漏与作用域越界(附JDK21真机调试录屏)
第一章:Java结构化并发崩溃了?手把手教你用VirtualThreadStructuredTaskScope定位线程泄漏与作用域越界(附JDK21真机调试录屏)Java 21 正式引入结构化并发(Structured Concurrency),其核心组件 …...
解锁3大自由:5分钟掌握的音乐格式解放工具
解锁3大自由:5分钟掌握的音乐格式解放工具 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 在数字音乐时代,我们却常常面临这样的困境:下载的音乐被限制在特定播放器中,就像拥有一本精美…...
突破B站缓存限制:m4s-converter视频格式转换完全指南
突破B站缓存限制:m4s-converter视频格式转换完全指南 【免费下载链接】m4s-converter 一个跨平台小工具,将bilibili缓存的m4s格式音视频文件合并成mp4 项目地址: https://gitcode.com/gh_mirrors/m4/m4s-converter 当旅行途中想离线观看缓存视频却…...
别再手动改配置了!用Docker Compose一键部署Pikachu靶场,5分钟搞定测试环境
5分钟极速搭建Pikachu靶场:Docker Compose自动化实战指南 每次准备网络安全练习环境时,最头疼的莫过于反复安装配置各种服务——PHP版本不兼容、MySQL连接失败、Web服务器配置错误...这些琐碎问题消耗了本应用于渗透测试学习的宝贵时间。今天要分享的这套…...
SiameseUIE部署指南:test.py中custom_entities字段详解
SiameseUIE部署指南:test.py中custom_entities字段详解 1. 概述 如果你正在使用SiameseUIE模型进行信息抽取,那么test.py脚本中的custom_entities字段就是你最需要关注的核心配置。这个看似简单的字段,实际上决定了模型如何精准地从文本中抽…...
需要控制重复点击按钮的通用方法
如图所示 在需要控制重复点击的地方使用通用方法去控制 省时省力 比用传统的分页定时器更方便...
mxbai-embed-large-v1 应用开发:从零构建智能文档检索系统
mxbai-embed-large-v1 应用开发:从零构建智能文档检索系统 1. 项目概述与核心价值 mxbai-embed-large-v1 是由 mixedbread-ai 开发的高性能文本嵌入模型,在 MTEB 基准测试中超越了 OpenAI text-embedding-3-large 等商业模型。该模型能够将文本转换为高…...
