TypeScript递归查找树节点并修改access及子节点isDisabled属性求助
问题分析
你的代码存在两个核心问题:
find函数内直接给参数data赋值属于修改局部变量,JS中对象参数是引用传递,直接给参数变量重新赋值不会修改原树中的对应节点,导致修改根本不生效。- 没有区分「匹配到目标节点前的遍历逻辑」和「匹配到目标节点后的修改逻辑」,原逻辑只会尝试修改匹配到的单个节点,没有把修改应用到整个子树,也不会保留其他分支的原有状态。
修正后代码(直接修改原数据,符合你现有调用习惯)
// 递归更新目标节点及其子树的逻辑 const updateNodeSubtree = (node: DataType, selectedAccess: 'view' | 'none', isTargetNode: boolean) => { // 修改当前节点属性 node.access = selectedAccess; if (selectedAccess === 'view') { node.isDisabled = false; } else { // access为none时,只有目标节点本身isDisabled是false,子节点都是true node.isDisabled = !isTargetNode; } // 递归更新所有子节点,子节点都不是目标节点 node.children.forEach(child => updateNodeSubtree(child, selectedAccess, false)); }; // 查找目标节点并触发更新 const find = (data: DataType, selectedId: string, selectedAccess: 'view' | 'none') => { if (!selectedId || !selectedAccess) return; // 匹配到目标节点,直接更新它和它的整个子树 if (data.id === selectedId) { updateNodeSubtree(data, selectedAccess, true); return; } // 没匹配到就遍历子节点继续找 data.children.forEach(child => find(child, selectedId, selectedAccess)); };
效果说明
调用方式和你原来完全一致,可100%匹配你给出的4条预期:
- 调用
find(Data, '2', 'none'):仅id为2、3的节点access改为none,2的isDisabled为false,3为true,其他节点不变 - 再调用
find(Data, '4', 'none'):仅id为4的节点access改为none、isDisabled为false,id4的子节点同步修改,id2、3的状态保留 - 调用
find(Data, '1', 'none'):所有节点access改为none,仅根节点1的isDisabled为false,其余全为true - 调用
find(Data, '1', 'view'):所有节点access改为view,所有节点isDisabled全为false
如果你需要不可变更新(不修改原数据,返回新的树对象),可以使用下面的版本:
const updateTreeImmutable = (node: DataType, selectedId: string, selectedAccess: 'view' | 'none', isTargetParent = false): DataType => { const isCurrentTarget = node.id === selectedId; const needUpdate = isCurrentTarget || isTargetParent; const newAccess = needUpdate ? selectedAccess : node.access; let newIsDisabled = node.isDisabled; if (needUpdate) { newIsDisabled = selectedAccess === 'view' ? false : !isCurrentTarget; } return { ...node, access: newAccess, isDisabled: newIsDisabled, children: node.children.map(child => updateTreeImmutable(child, selectedId, selectedAccess, isCurrentTarget || isTargetParent)) } }; // 调用方式:const newData = updateTreeImmutable(Data, '2', 'none')
内容的提问来源于stack exchange,提问作者webber
相关产品推荐
相关产品推荐

