【Ant-Desgin-React 穿梭框】表格穿梭框,树穿梭框的用法

Antd Desgin 穿梭框

  • 普通用法
  • 高级用法-表格穿梭框组件
  • 高级用法-树穿梭框组件

普通用法

/* eslint-disable no-unused-vars */
import React, { useEffect, useState } from 'react'
import { Space, Transfer } from 'antd'// Antd的穿梭框组件Mock数据
const mockData = Array.from({length: 20
}).map((_, i) => ({key: i.toString(),title: `content${i + 1}`,description: `description of content${i + 1}`,disabled: i % 3 < 1 // 禁用某项
}))// 筛选出ID数组
const initialTargetKeys = mockData.filter(item => Number(item.key) > 10).map(item => item.key)const App = () => {// 设置目标键数组const [targetKeys, setTargetKeys] = useState(initialTargetKeys)// 设置选中的键数组const [selectedKeys, setSelectedKeys] = useState([])useEffect(() => {console.log('模拟数据', mockData)}, [])const onChange = (nextTargetKeys, direction, moveKeys) => {console.log('==========Start Change==========')console.log('targetKeys:', nextTargetKeys) // 下一次的目标键数组,即移动后的目标列表console.log('direction:', direction) // 移动的方向,可以是'left'或'right',表示从左侧列表移动到右侧列表或从右侧列表移动到左侧列表console.log('moveKeys:', moveKeys) // 移动的键数组,即移动的项console.log('==========End Change==========')setTargetKeys(nextTargetKeys)}const onSelectChange = (sourceSelectedKeys, targetSelectedKeys) => {console.log('==========Start SelectChange==========')console.log('sourceSelectedKeys:', sourceSelectedKeys) // 源列表中选中的键数组console.log('targetSelectedKeys:', targetSelectedKeys) // 目标列表中选中的键数组console.log('==========End SelectChange==========')setSelectedKeys([...sourceSelectedKeys, ...targetSelectedKeys])}const onScroll = (direction, e) => {console.log('==========Start Scroll==========')console.log('direction:', direction) // 滚动的方向,可以是'left'或'right',表示向左滚动或向右滚动console.log('target:', e.target) // 滚动事件对象,包含了滚动的相关信息,如滚动的目标等console.log('==========End Scroll==========')}console.log('==========Start Search==========')const handleSearch = (dir, value) => {// dir 表示搜索框所在的列表,可以是'left'或'right',表示在源列表或目标列表中搜索\// value 表示搜索框中的值console.log('search:', dir, value)}console.log('==========End Search==========')return (<div className="App"><Space><TransferdataSource={mockData} // 数据源,即需要在两个列表之间移动的数据列表titles={['Source', 'Target']} // 列表的标题,包括源列表和目标列表的标题targetKeys={targetKeys} // 目标列表中的键数组,表示当前已经选中的项的键数组selectedKeys={selectedKeys} // 当前选中的项的键数组,用于在两个列表之间移动项时的状态管理onChange={onChange} // 当目标列表中的键数组改变时触发的事件回调函数onSelectChange={onSelectChange} // 当源列表和目标列表中的选中项改变时触发的事件回调函数onScroll={onScroll} // 当滚动时触发的事件回调函数onSearch={handleSearch} // 当搜索框中的值改变时触发的事件回调函数render={item => item.title} // 定义如何渲染每个数据项,返回一个React元素oneWay // 是否只允许从左侧列表向右侧列表移动数据,默认为falseshowSearch // 是否显示搜索框,默认为falsepagination // 是否显示分页,默认为false,一般在大数据量下使用/>{/* 自定义状态 */}<Transfer status="error" /><Transfer status="warning" showSearch /></Space></div>)
}export default App

在这里插入图片描述

高级用法-表格穿梭框组件

/* eslint-disable react/prop-types */
/* eslint-disable no-unused-vars */
import React, { useState } from 'react'
import { Space, Switch, Table, Tag, Transfer } from 'antd'// leftColumns 表示左侧表格的列,rightColumns表示右侧表格的列,restProps表示其他属性
const TableTransfer = ({ leftColumns, rightColumns, ...restProps }) => (// 渲染Transfer组件<Transfer {...restProps}>{({direction, // 数据传输方向(左或右)filteredItems, // 经过搜索过滤后的项onItemSelect, // 选中项时的回调函数onItemSelectAll, // 全选项时的回调函数selectedKeys: listSelectedKeys, // 已选中项的键数组disabled: listDisabled // 列表是否被禁用的标志}) => {const columns = direction === 'left' ? leftColumns : rightColumns // 根据传输方向选择表格列const rowSelection = {getCheckboxProps: () => ({disabled: listDisabled // 设置复选框是否禁用}),onChange(selectedRowKeys) {onItemSelectAll(selectedRowKeys, 'replace') // 全选/取消全选时的操作},selectedRowKeys: listSelectedKeys, // 已选中项的键数组selections: [Table.SELECTION_ALL, Table.SELECTION_INVERT, Table.SELECTION_NONE] // 表格行选择器}return (<TablerowSelection={rowSelection} // 表格行选择器配置columns={columns} // 表格列配置dataSource={filteredItems} // 数据源size="small" // 表格尺寸style={{pointerEvents: listDisabled ? 'none' : undefined // 根据列表是否禁用设置CSS样式}}onRow={({ key, disabled: itemDisabled }) => ({// 表格行的事件处理函数onClick: () => {if (itemDisabled || listDisabled) {// 如果项被禁用或列表被禁用,则不执行操作return}onItemSelect(key, !listSelectedKeys.includes(key)) // 选中/取消选中项时的操作}})}/>)}}</Transfer>
)const mockTags = ['cat', 'dog', 'bird'] // 模拟标签数据
const mockData = Array.from({// 生成模拟数据length: 20
}).map((_, i) => ({key: i.toString(), // 唯一键title: `content${i + 1}`, // 标题description: `description of content${i + 1}`, // 描述tag: mockTags[i % 3] // 标签
}))
// 表格列配置
const columns = [{dataIndex: 'title',title: 'Name'},{dataIndex: 'tag',title: 'Tag',render: tag => (<Tagstyle={{marginInlineEnd: 0}}color="cyan">{tag.toUpperCase()}</Tag>)},{dataIndex: 'description',title: 'Description'}
]
const Default = () => {const [targetKeys, setTargetKeys] = useState([]) // 目标键数组的状态及其更新函数const [disabled, setDisabled] = useState(false) // 禁用状态及其更新函数const onChange = nextTargetKeys => {// 目标键数组变化时的处理函数setTargetKeys(nextTargetKeys) // 更新目标键数组}const toggleDisabled = checked => {// 切换禁用状态的处理函数setDisabled(checked) // 更新禁用状态}return (<><TableTransfer // 表格数据传输组件dataSource={mockData} // 数据源targetKeys={targetKeys} // 目标键数组disabled={disabled} // 是否禁用showSearch // 是否显示搜索框showSelectAll={false} // 是否显示全选按钮onChange={onChange} // 目标键数组变化时的回调函数filterOption={(inputValue,item // 自定义搜索过滤函数) => item.title.indexOf(inputValue) !== -1 || item.tag.indexOf(inputValue) !== -1}leftColumns={columns} // 左侧表格列配置rightColumns={columns} // 右侧表格列配置/><Spacestyle={{marginTop: 16}}>{/* 开关组件,用于切换禁用状态 */}<Switch unCheckedChildren="disabled" checkedChildren="disabled" checked={disabled} onChange={toggleDisabled} /></Space></>)
}
export default Default

在这里插入图片描述

高级用法-树穿梭框组件

未完善

TreeTransfer.jsx 树穿梭框组件

/* eslint-disable no-unused-vars */
/* eslint-disable react/prop-types */
import React, { useEffect, useState } from 'react'
import { Transfer, Tree } from 'antd'const generateTree = (treeNodes = [], checkedKeys = [], parentKeys = []) =>treeNodes.map(({ children, ...props }) => {const updatedProps = {...props,disabled: checkedKeys.includes(props.key),children: generateTree(children, checkedKeys, parentKeys.concat(props.key))}// 父节点如果被选中,则添加所有子节点到 checkedKeysif (checkedKeys.includes(props.key)) {updatedProps.children.forEach(child => {if (!checkedKeys.includes(child.key)) {checkedKeys.push(child.key)}})}return updatedProps})const TreeTransfer = ({ dataSource, ...restProps }) => {const [selectedKeys, setSelectedKeys] = useState([])const [targetKeys, setTargetKeys] = useState([])useEffect(() => {console.log(selectedKeys, 'selectedKeys')}, [selectedKeys, setSelectedKeys])// 子节点全部选中时,让父节点也会被选中// key 表示当前节点,checkedKeys 是当前目标源keys数组,dataSource 是数据数组const updateParentKeys = (key, checkedKeys, dataSource) => {console.log(key, '当前节点', checkedKeys, '当前目标源keys数组', dataSource, '数据数组')// 对 checkedKeys 做浅拷贝,以避免直接修改原数组const updatedKeys = [...checkedKeys]// 查找包含指定子节点键 key 的父节点const parentNode = dataSource.find(item => item.children && item.children.some(child => child.key === key))if (parentNode) {// 如果找到了父节点// 检查父节点的所有子节点是否都在 updatedKeys 中const allChildrenChecked = parentNode.children.every(child => updatedKeys.includes(child.key))// 如果所有子节点都被选中且父节点未被选中,则将父节点添加到 updatedKeys 中if (allChildrenChecked && !updatedKeys.includes(parentNode.key)) {updatedKeys.push(parentNode.key)} else if (!allChildrenChecked && updatedKeys.includes(parentNode.key)) {// 如果存在未被选中的子节点且父节点被选中,则从 updatedKeys 中移除父节点updatedKeys.splice(updatedKeys.indexOf(parentNode.key), 1)}// 递归更新父节点的父节点,确保所有相关节点的选中状态都被正确更新return updateParentKeys(parentNode.key, updatedKeys, dataSource)}// 如果没有找到父节点,则直接返回 updatedKeysreturn updatedKeys}const handleCheck = (checkedKeys, { node: { key, children } }) => {let cKeys = [...selectedKeys] // 复制当前已选择的键数组// 如果点击的节点已经在已选择数组中,则从数组中移除if (cKeys.includes(key)) {cKeys = cKeys.filter(item => item !== key)if (children && children.length > 0) {const checkList = dataSource.filter(item => item.key === key).map(item => {return [key, ...item.children.map(child => child.key)]}).flat()console.log(checkList, '取消选择的父节点')// 使用 Array.prototype.filter() 来移除整个节点数组cKeys = cKeys.filter(item => !checkList.includes(item))} else {// 如果点击的是子节点,则检查父节点是否需要从已选择数组中移除cKeys = updateParentKeys(key, cKeys, dataSource)}} else {// 将当前节点添加到已选择数组中cKeys.push(key)// 如果点击的是父节点,则同时将子节点也添加到已选择数组中if (children && children.length > 0) {children.forEach(child => {cKeys.push(child.key)})} else {// 如果点击的是子节点,则检查父节点是否需要添加到已选择数组中cKeys = updateParentKeys(key, cKeys, dataSource)}}setSelectedKeys(cKeys)}const onChange = (t, d, m) => {setTargetKeys(selectedKeys)}return (<Transfer{...restProps}targetKeys={targetKeys}selectedKeys={selectedKeys}dataSource={dataSource}onChange={onChange}render={item => item.title}showSelectAll={false}oneWay>{({ direction }) => {if (direction === 'left') {const checkedKeys = [...selectedKeys, ...targetKeys]return (<TreeblockNodecheckablecheckStrictlydefaultExpandAllcheckedKeys={checkedKeys}treeData={generateTree(dataSource, targetKeys)}onCheck={handleCheck}onSelect={handleCheck}/>)}}}</Transfer>)
}export default TreeTransfer

Index.jsx

/* eslint-disable no-unused-vars */
/* eslint-disable react/prop-types */
import React, { useState } from 'react'
import TreeTransfer from './dom';const treeData = [{key: '0-0',title: '0-0'},{key: '0-1',title: '0-1',children: [{key: '0-1-0',title: '0-1-0'},{key: '0-1-1',title: '0-1-1'}]},{key: '0-2',title: '0-2'},{key: '0-3',title: '0-3'},{key: '0-4',title: '0-4'}
]const Index = () => {return <TreeTransfer dataSource={treeData} />
}
export default Index

在这里插入图片描述

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

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

相关文章

西安站开营!AI 编码助手通义灵码帮大学生“整活儿”

如何更好地与 AI 为伴&#xff0c;做时代的先进开发者&#xff1f;4 月 17 日&#xff0c;阿里云推出的 AI 编程助手通义灵码与云工开物“高校训练营”走进西安多所高校开启实操培训&#xff0c;结合 AI 辅助编程的发展背景、通义灵码的具体能力和应用实操&#xff0c;帮助在校…

全世界IT人苦竞业久矣!美国FTC宣布全面废除员工竞业协议

2023 年 1 月&#xff0c;美国联邦贸易委员会&#xff08;FTC&#xff09;发布声明称&#xff0c;拟在全国范围禁止用人单位与雇员签订竞业禁止性条款。当地时间 4 月 23 日&#xff0c;FTC 宣布全面禁止所有员工&#xff08;包括高级管理人员&#xff09;签署新的竞业禁止协议…

js生成不同的阅读数分配到每一篇上面,不会因为刷新而变动

js生成不同的阅读数分配到每一篇上面,不会因为刷新而变动 {%- for article in blog.articles -%}<div class"blog-articles__article article">{%- render article-card,article: article,media_height: section.settings.image_height,media_aspect_ratio: a…

xilinx Mailbox 中的ipi message地址计算方式

适用于openAmp mailbox ipi id对应的ipi message地址计算方式 官方openamp硬件配置解析 OpenAMP Base Hardware Configurations - Xilinx Wiki - Confluence openamp官方设备树 meta-openamp/meta-xilinx-tools/recipes-bsp/device-tree/files/zynqmp-openamp.dtsi at rel-v2…

SpringBoot+Vue开发记录(四)

说明&#xff1a; 本篇文章的主要内容是软件架构以及项目的前端Vue创建 一、软件架构 我道听途说的&#xff0c;听说这个东西很关键很重要什么的。 软件架构&#xff08;software architecture&#xff09;是一个系统的草图,是一系列相关的抽象模式&#xff0c;用于指导大型软…

AI商业智能的一些分享

本文主要讲AI商业相关的&#xff08;特别是营销相关的&#xff09;一些知识点&#xff0c;比较零散。 简单总结 AI商业智能&#xff1a; 1&#xff09;将人员经验抽象化为算法规则&#xff0c; 2)打造数据驱动的精益运营能力&#xff0c; 3)长期保持价格竞争力并将商品毛利让…

Day 21 LAMP架构和DNS域名

LAMP架构简介 针对不同的后端开发语言&#xff0c;使用不同的架构&#xff0c;后端项目开发语言有&#xff1a;Java&#xff0c;PHP&#xff0c;Python...... 针对于PHP项目 LAMP架构 LinuxApacheMysql/MariadbPhp LNMP架构 LinuxNginxMysql/MariadbPhp 针对于Java项目 w…

国密SSL证书在等保、关保、密评合规建设中的应用

在等保、关保、密评等合规建设中&#xff0c;网络和通信安全方面的建设是非常重要的部分&#xff0c;需要实现加密保护和安全认证&#xff0c;确保传输数据机密性、完整性以及通信主体可信认证。国密SSL证书应用于等保、关保和密评合规建设中&#xff0c;不仅能够提升网络信息系…

【C++】vector常用函数总结及其模拟实现

目录 一、vector简介 二、vector的构造 三、vector的大小和容量 四、vector的访问 五、vector的插入 六、vector的删除 简单模拟实现 一、vector简介 vector容器&#xff0c;直译为向量&#xff0c;实践中我们可以称呼它为变长数组。 使用时需添加头文件#include<v…

【Burpsuite靶场】XSS专题精讲

【个人】&#xff1a;NEUQ大一学生 【专业】&#xff1a;通信工程 (Communication Engineering) 【个人方向】&#xff1a;网安、开发双管齐下 【座右铭】&#xff1a;真正的英雄主义,就是看清生活的真相后依然热爱生活 -- 罗曼.罗兰 一、认识XSS&#xff08;跨站脚本攻击&…

零基础转行网络安全,难度大吗?

说有难度那是肯定会有的&#xff0c;事在人为&#xff0c;我之前是从事于Java后端开发的&#xff0c;后面转行学网络安全&#xff0c;花了些时间&#xff0c;现在拿到了比之前开发更高的薪资&#xff0c;觉得还是挺满足的&#xff01; 1.网络安全岗位 1.1安全运维工程师 负责监…

【Python数据库】MySQL

文章目录 [toc]创建数据库创建数据表数据插入数据查询数据更新 个人主页&#xff1a;丷从心 系列专栏&#xff1a;Python数据库 学习指南&#xff1a;Python学习指南 创建数据库 import pymysqldef create_database():db pymysql.connect(hostlocalhost, userroot, passwor…

Maven多模块快速升级超好用Idea插件-MPVP

功能&#xff1a;多模块maven项目快速升级指定版本插件&#xff0c;并提供预览和相关升级模块日志能力。 可快速进行版本升级&#xff0c;进行部署到Maven仓库。 安装&#xff1a; 可在idea插件中心进行安装 / 下载资源拖动安装 MPVP(Maven) - IntelliJ IDEs Plugin | Marke…

遥测终端赋能水库泄洪监测预警,筑牢度汛安全防线!

4月10日&#xff0c;水利部召开水库安全度汛视频会议。会议要求着力强化水库防洪“四预”措施&#xff0c;加快构建雨水情监测预报“三道防线”&#xff0c;完善预警信息发布机制&#xff0c;推进数字孪生水利工程建设&#xff0c;为科学调度指挥决策提供支持。强调坚决牢牢守住…

Ubuntu Pycharm安装

下载PyCharm&#xff0c;https://www.jetbrains.com/pycharm/download/?sectionlinux 然后按照下图执行安装&#xff1a; 安装的时候可能出现的问题&#xff1a; 问题1&#xff1a;No JDK found. Please validate either PYCHARM_JDK, JDK_HOME or JAVA_HOME environment var…

【熵与特征提取】从近似熵,到样本熵,到模糊熵,再到排列熵,包络熵,散布熵,究竟实现了什么?(第六篇)——“散布熵”及其MATLAB实现

今天讲散布熵&#xff0c;之前用了几篇文章分别讲述了功率谱熵、奇异谱熵、能量熵、近似熵、样本熵、模糊熵、排列熵、包络熵这8种类型的熵&#xff1a; Mr.看海&#xff1a;【熵与特征提取】基于“信息熵”的特征指标及其MATLAB代码实现&#xff08;功率谱熵、奇异谱熵、能量…

使用API有效率地管理Dynadot域名,自查账户信息

关于Dynadot Dynadot是通过ICANN认证的域名注册商&#xff0c;自2002年成立以来&#xff0c;服务于全球108个国家和地区的客户&#xff0c;为数以万计的客户提供简洁&#xff0c;优惠&#xff0c;安全的域名注册以及管理服务。 Dynadot平台操作教程索引&#xff08;包括域名邮…

使用Python进行异常处理与日志记录的最佳实践

&#x1f47d;发现宝藏 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。 使用Python进行异常处理与日志记录的最佳实践 异常处理和日志记录是编写可靠且易于维护的软…

Hive——DML(Data Manipulation Language)数据操作语句用法详解

DML 1.Load Load语句可将文件导入到Hive表中。 hive> LOAD DATA [LOCAL] INPATH filepath [OVERWRITE] INTO TABLE tablename [PARTITION (partcol1val1, partcol2val2 ...)];关键字说明&#xff1a; local&#xff1a;表示从本地加载数据到Hive表&#xff1b;否则从HD…

Linux gcc day7

动态链接和静态链接 形成的可执行的程序小&#xff1a;节省资源--内存&#xff0c;磁盘 无法c静态库链接的方法 原因是我们没有安装静态c库&#xff08;.a&#xff09; 所以要安装 sudo yum install -y glibc-static gcc static静态编译选项提示错误&#xff1a;/usr/lib/ld:ca…