React中基于react-dual-listbox的权限数组递归校验与去重需求
权限转移处理函数实现方案
需求概述
需要实现一个处理权限转移的函数,接收两个数组参数:
- 当前已选中的权限数组:存储最终保留的权限项
- 待转移的选中权限数组:
react-dual-listbox组件onChange回调返回的新选中权限项集合
函数需满足以下逻辑:
- 若待转移的权限项已存在于当前数组中,移除原有项并保留新转移的项
- 递归检查待转移权限的所有子权限,若这些子权限已存在于当前数组中,同样移除
示例场景:先向空数组添加ROLE_READ,后续添加ROLE_EDIT时,需移除已存在的ROLE_READ(因为ROLE_EDIT包含该子权限)
数据格式示例
带子权限的权限列表结构
[ { "name": "ROLE_READ", "subPermissions": [] }, { "name": "ROLE_DELETE", "subPermissions": [ { "name": "ROLE_READ", "subPermissions": [ { "name": "ROLE_WRITE", "subPermissions": [ { "name": "ROLE_EDIT", "subPermissions": [] } ] } ] } ] }, { "name": "ROLE_EDIT", "subPermissions": [ { "name": "ROLE_READ", "subPermissions": [] } ] }, { "name": "PROJECT_MEMBER_READ", "subPermissions": [] }, { "name": "PROJECT_MEMBER_EDIT", "subPermissions": [ { "name": "PROJECT_MEMBER_READ", "subPermissions": [] } ] } ]
React组件配置说明
使用react-dual-listbox时需注意以下配置:
- 必须设置
simpleValue={false},确保onChange返回完整的权限对象数组 - 原始权限数据适配组件格式的转换代码:
const data = options.map(rest => ({ ...rest, label: rest.name, value: rest.name }));
- 组件基础使用示例:
import DualListBox from 'react-dual-listbox'; import 'react-dual-listbox/lib/react-dual-listbox.css'; // ... <DualListBox options={data} selected={finalArray} onChange={(selected) => { setFinalArray(prev => handlePermissionTransfer(prev, selected)); }} simpleValue={false} />
核心函数实现
1. 递归获取权限及其所有子权限的名称集合
用于快速判断哪些权限需要被移除:
const getAllPermissionNames = (permission) => { let names = [permission.name]; permission.subPermissions.forEach(subPerm => { names = [...names, ...getAllPermissionNames(subPerm)]; }); return names; };
2. 权限转移处理核心函数
const handlePermissionTransfer = (currentPermissions, selectedPermissions) => { // 收集待转移权限及其所有子权限的名称 const newPermNames = new Set(); selectedPermissions.forEach(perm => { getAllPermissionNames(perm).forEach(name => newPermNames.add(name)); }); // 过滤当前数组:移除所有被新权限覆盖的项(包含子权限已存在的项) const filteredCurrent = currentPermissions.filter(perm => !newPermNames.has(perm.name)); // 合并过滤后的数组与新选中的权限(自动去重,因为已移除冲突项) return [...filteredCurrent, ...selectedPermissions]; };
内容的提问来源于stack exchange,提问作者Baran Öden
相关产品推荐
相关产品推荐

