穿梭框是什么?怎么使用?
需求如下:
有一组端口需要分配给具体接口
功能要求:
-
需要展示当前端口名称及其所属的接口
-
需支持搜索功能可对端口名或接口名进行筛选便于分配
-
分配端口时,需检测当前接口内的端口是否满足此接口最低要求
-
提供Select下拉框,可供查看及操作具体接口内的端口
-
保存操作时,需对各接口数据进行最低要求效验
-
操作不满足条件时,需中断数据操作,并展示操作项异常状态
原理:左侧为数据集合,右侧为设置的数据的key值集合
效果图如下:

穿梭框简单用法(基础属性介绍):
javascript
<Transfer
dataSource={staffKeyArr}
titles={['任务总人员', 'A任务人员']} //标题集合
targetKeys={AStaffKeyArr} // 显示在右侧的key集合
// selectedKeys={selectedKeys} // 默认被选中的集合
//
onChange={onChange} // 具体数据操作
onSelectChange={onSelectChange} // 选中项发生改变
//
showSearch // 是否展示搜索功能
// onSearch={handleSearch}
filterOption={seachFn} // 具体搜索操作
//
operations={['to right', 'to left']} // 穿梭框中间图标描述
// 同时设置两侧的样式
listStyle={{
width: 300,
height: 300,
}}
// 单独设置两侧的样式
// listStyle={(direction) => {
// if (direction === 'left') {
// return {
// width: 300,
// backgroundColor: '#f5f5f5',
// border: '1px solid #1890ff',
// }
// } else {
// return {
// width: 350,
// backgroundColor: '#fffbe6',
// border: '1px dashed #ffa940',
// }
// }
// }}
//
// pagination // 是否使用分页
pagination={{
pageSize: 5,
showSizeChanger: true, //是否显示分页器
}}
//
render={(item) => {
// 一般穿梭框渲染项
return item.name
}}
/>
上述代码中的函数介绍,更多函数可查看官网,地址如下:穿梭框 Transfer - Ant Design
常用函数介绍:
tips:掌握onChange+filterOption能解决大部分操作
javascript
// 点击穿梭框中间的图标时的实际操作
const onChange = (nextTargetKeys, direction, moveKeys) => {
// nextTargetKeys 移动后的key值集合
// direction 当前动作
// moveKeys 当前选中的key值
setbrWanKeyArr(nextTargetKeys)
}
// 搜索实际数据处理函数
const seachFn = (value, item, direction) => {
// value 当前搜索的值
// item 此处可以把次函数理解为filter,item为当前操作的穿梭框内的每一项
// direction 当前操作的穿梭框位置
return (
// 此处对name属性进行筛选(可对多数据进行筛选)
item.name.indexOf(value) !== -1
)
}
// 对穿梭框的内容选中时触发
const onSelectChange = (sourceSelectedKeys, targetSelectedKeys) => {
// sourceSelectedKeys 当前选中的key值
// targetSelectedKeys 当前的具体数值
console.log(sourceSelectedKeys, targetSelectedKeys, 123)
}
// 搜索时触发
const handleSearch = (direction, value) => {
// direction 当前操作的穿梭框位置
// value 当前搜索的值
console.log('search:', direction, value)
}
穿梭框高阶用法表格穿梭框:
使用场景: 简单穿梭框只能渲染数据中的一项,使用表格穿梭框可随意渲染数据中的任意项
在基础穿梭框的用法上,加以封装调整,代码如下:
表格穿梭框封装处理后使用
javascript
const Default = (props) => {
// 表格渲染
const columns = [
{
dataIndex: 'key',
title: '端口名称',
},
{
dataIndex: 'alias',
title: '所属接口',
render: (tag) => (
<Tag className="TagCol1">{tag}</Tag>
),
},
]
// 总端口
const [totalInter, setTotalInter] = useState()
// 当前分配的接口
const [nowInter, setNowInter] = useState()
// 当前分配的接口数据
const [nowKeys, setNowKeys] = useState([])
// 需要禁用的端口列表
const [disableList, setDisableList] = useState([])
// 异常状态动态类名控制
const [errorStatus, setErrorStatus] = useState()
useEffect(() => {
// 此处对初始各数据进行处理/赋值
}, [])
// 数据发生变动时触发
const onChange = (nextTargetKeys, direction, moveKeys) => {
// 对当前的操作进行条件1效验,并赋予异常状态
if (flagXXX) {
setErrorStatus('TransferRight')
return
} else {
setErrorStatus('')
}
// 需要实时数据更新,即需对总数据进行实时更改
setTotalInter((prev) => {
prevxxx
})
// 更新当前右侧分配的接口数据的key值集合
setNowKeys(nextTargetKeys)
}
// 右侧数据进行切换时触发
const changeRightData = (val, error) => {
// 存储当前所操作的接口标识
setNowInter(val)
// 更新当前右侧分配的接口数据的key值集合
setNowKeys(XXXXchangeData)
// 对当前的操作进行条件2效验,并赋予异常状态
if (flagXXX) {
setErrorStatus('TransferRight')
} else {
setErrorStatus('')
}
}
// 搜索时触发
const seachFn = (val, item, direction) => {
// 当前支持搜索端口名称及所属接口
return item.key.indexOf(val) !== -1 || item.alias.indexOf(val) !== -1
}
// 保存操作时触发
const saveData = () => {
// 对当前的操作进行条件3效验,并赋予异常状态
let vad = false
let athArr = totalInter.filter((item) => {
if (XXX) return XXX
})
athArr.forEach((item) => {
if (flagXXX) {
vad = true
setErrorStatus('TransferLeft')
return
}
})
if (vad) return
// 对当前的操作进行条件4效验,并赋予异常状态
let arrEmpty = false
lastArr.forEach((item) => {
if (flagXXX) {
arrEmpty = true
return
}
})
if (arrEmpty) return
// 所有效验通过后触发函数
props.save(lastArr)
}
return (
<>
<TableTransfer
dataSource={totalInter} // 数据源
targetKeys={nowKeys} // 当前右侧操作的接口数据key值集合
showSelectAll={false}
onChange={onChange}
showSearch
filterOption={seachFn}
Columns={columns} // 表格渲染规则
operations={['分配', '重置']}
// 以下为自定义传递
changeRightData={changeRightData} // 右侧插入的下拉框切换数据函数
selectList={selectList} // 动态下拉框列表
disabledList={disableList} // 动态禁用项
transferStatus={errorStatus} // 动态类名,控制左侧或右侧异常
nowInter={nowInter} // 动态控制当前操作的接口
/>
<Button type="primary" onClick={saveData}>
{L.Save}
</Button>
</>
)
}
export default Default
表格穿梭框封装处理
javascript
// 对穿梭框进行封装
const TableTransfer = ({ Columns, transferStatus, ...restProps }) => {
return (
// className={transferStatus} 控制异常状态
<Transfer className={transferStatus} {...restProps}>
{({
direction,
filteredItems,
onItemSelect,
onItemSelectAll,
selectedKeys: selectedList,
}) => {
const columns = Columns
// antd的表格功能配置项,具体可查看官网
const rowSelection = {
// 选择框的默认属性配置 (禁用)
getCheckboxProps: (item) => {
return {
disabled:
restProps.disabledList.indexOf(item.key) !== -1,
}
},
// 全选操作处理
onChange: (nowKeys, keysData) => {
onItemSelectAll(nowKeys, 'replace')
},
selectedRowKeys: selectedList,
selections: [
Table.SELECTION_ALL,
Table.SELECTION_INVERT,
Table.SELECTION_NONE,
],
}
return (
<>
{/* 插入的Select下拉框 */}
{/* direction === 'right' 只插入右侧
restProps.selectList[0] 下拉框初始值渲染处理
*/}
{direction === 'right' && restProps.selectList[0] && (
<div>
<Select
onChange={(val) => {
restProps.changeRightData(val)
}} // 切换数据处理函数
value={restProps.nowInter}
options={restProps.selectList}
/>
</div>
)}
<Table
rowSelection={rowSelection}
columns={columns}
dataSource={filteredItems}
size="small"
// 可对表格行数据进行操作处理
onRow={({ key }) => ({
onClick: () => {
onItemSelect(
key,
!listSelectedKeys.includes(key)
)
},
})}
/>
</>
)
}}
</Transfer>
)
}