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

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

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

相关文章

MFC GDI 绘图模式、映射模式、画笔、笔、字体

一 GDI 绘图模式&#xff08;RoP2 Mode&#xff09; 在使用VC MFC进行图形程序编程时&#xff0c;常会用到GDI绘图指令&#xff0c;而要做到绘图时有橡皮筋动态效果&#xff0c;就需设置GDI绘图模式。GDI绘图模式有多种&#xff0c;如下&#xff1a; 常用R2_NOT模式来实…

如何修复 System has not been booted with systemd 报错信息?

如何修复 System has not been booted with systemd 报错信息&#xff1f; 一、问题描述&#xff1a; 我们在学习 linux 系统时&#xff0c;使用 systemd 命令&#xff08;比如 sudo systemctl status ssh&#xff09;&#xff0c;可能会遇到一个报错信息&#xff1a; System…

VS2022上通过C++绘图库ROOT库绘制一个3D曲面图

ROOT库提供了强大的交互式图形功能。通过使用ROOT库的TCanvas和TApplication类&#xff0c;可以创建一个交互式的图形窗口&#xff0c;可以对图形进行缩放、平移、旋转等操作&#xff0c;并且可以通过鼠标和键盘与图形进行交互&#xff0c;这点实在是太厉害了&#xff0c;也就是…

Macos14.4 安装MySQL5.7

文章目录 前言一、MySQL介绍二、安装步骤1.下载2.安装3.配置1.进入系统设置2.启动服务3.配置环境变量4.修改密码 FAQ1.双击安装时提示&#xff1a;检测恶意软件&#xff0c;无法打开2.修改环境变量文件提示&#xff1a;readonly option is set (add ! to override)文件权限不足…

QT常量中有换行符

头文件添加&#xff1a; #pragma execution_character_set("utf-8")

Fastjson漏洞之CVE-2017-18349

前言&#xff1a; 要想理解漏洞原理&#xff0c;首先看看Fastjson是什么&#xff0c;具体用来做什么才能更好的找到可以利用的场景&#xff1a; Fastjson 是一个由阿里巴巴开发的 Java 语言实现的高性能 JSON 解析器和生成器。它具有以下特点: 快速&#xff1a;Fastjson 在序列…

接口测试基础

Postman断言 1、Postman断言介绍 l 作用&#xff1a;让Postman工具代替人工 自动判定 预期结果和实际结果是否一致。 2、Postman断言——响应状态码断言 l 模板名称&#xff1a;Status code: Code is 200 l 模板内容&#xff1a; 2、Postman断言——包含指定字符串断言 …

在Linux上面部署ELK

注明&#xff1a;一下的软件需要自己准备 一、准备环境&#xff1a; 1.两台elasticsearch主机4G内存 2.两台elasticsearch配置主机名node1和node2(可以省略) #vim /etc/hostname #reboot 3. 两台elasticsearch配置hosts文件 #vim /etc/hosts 192.168.1.1 node1 192…

安卓开发:相机水印设置

1.更新水印 DecimalFormat DF new DecimalFormat("#"); DecimalFormat DF1 new DecimalFormat("#.#");LocationManager LM (LocationManager)getSystemService(Context.LOCATION_SERVICE); LM.requestLocationUpdates(LocationManager.GPS_PROVIDER, 2…

《欢乐钓鱼大师》辅助:新手钓鱼全新攻略大全!

《欢乐钓鱼大师》是一款充满趣味和挑战的钓鱼游戏。在游戏中&#xff0c;玩家不仅可以体验钓鱼的乐趣&#xff0c;还可以通过不同的钓鱼竿和鱼卡来提升自己的钓鱼技能。为了帮助新手和老玩家更好地体验游戏&#xff0c;本文将为您提供详细的游戏攻略。 1. 游戏目标 在《欢乐钓…

一个人应该怎么操作抖音小店呢?店铺操作流程给你讲解清楚!

大家好&#xff0c;我是电商小V 现在入驻抖音小店的有很多新手&#xff0c;新手最关心的就是一个人应该如何操作抖音小店&#xff0c;操作抖音小店需要做好哪几步呢&#xff1f;关于这个问题咱们就来详细的讲解一下&#xff0c; 第一点&#xff1a;开店 开店是做店的第一步&…

【资讯】5月巴塞罗那,东胜物联边缘计算网关亮相IOTSWC AWS展台

2024年5月21-23日&#xff0c;物联网解决方案世界大会 IOT SWC 在巴塞罗那举行&#xff0c;这是数字化转型趋势和颠覆性技术的顶级盛会。 作为AWS的硬件合作伙伴&#xff0c;东胜物联网边缘计算网关DSGW-210将在AWS展台1号馆展出&#xff0c;欢迎大家前来参观。 此次东胜在AW…

FPGA之tcp/udp

在调试以太网的过程中&#xff0c;考虑了vivado IP配置(管脚、reset等)&#xff0c;SDK中PHY芯片的配置(芯片地址、自适应速率配置等)&#xff0c;但是&#xff0c;唯独忽略了tcp/udp协议&#xff0c;所以在ping通之后仍无法连接。 所以现在来学习一下tcp与udp的区别 ---- 为什…

.NET 一款内部最新的免杀WebShell

01阅读须知 此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等&#xff08;包括但不限于&#xff09;进行检测或维护参考&#xff0c;未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供的信息而造成的直接或间接后果和损失&#xf…

勒索软件分析_Conti

0. Conti介绍 勒索软件即服务&#xff08;Ransomware as a Service&#xff0c;RaaS&#xff09;变体 Conti 推出还不到两年&#xff0c;已经进行了第七次迭代。Conti被证明是一种敏捷而熟练的恶意软件威胁&#xff0c;能够自主和引导操作&#xff0c;并具有无与伦比的加密速度…

等保2.0看这一篇就够了

一、等级保护介绍 1.1什么是等级保护 网络安全等级保护是指对国家重要信息、法人和其他组织及公民的专有信息以及信息和存储、传输、处理这些信息的信息系统分等级实行安全保护&#xff0c;对信息系统中使用的信息安全产品实行按等级管理&#xff0c;对信息系统中发生的信息安…

2024年云南特岗教师报名流程,超详细,明天就开始报名哦!

2024年云南特岗教师报名流程&#xff0c;超详细&#xff0c;明天就开始报名哦&#xff01;

Android四大组件 Broadcast广播机制

一 概述 广播 (Broadcast) 机制用于进程或线程间通信&#xff0c;广播分为广播发送和广播接收两个过程&#xff0c;其中广播接收者 BroadcastReceiver 是 Android 四大组件之一。BroadcastReceiver 分为两类&#xff1a; 静态广播接收者&#xff1a;通过 AndroidManifest.xm…

SQL——SELECT相关的题目

目录 197、上升的温度 577、员工奖金 586、订单最多的客户 596、超过5名学生的课 610、判断三角形 620、有趣的电影 181、超过经理收入的员工 1179、重新格式化部门表&#xff08;行转列&#xff09; 1280、学生参加各科测试的次数 1068、产品销售分析I 1075、项目员工I …