对代码中涉及 `localStorage` 的部分的详细注释和讲解
在你提供的 React 代码中,localStorage 被用来存储和恢复树节点的展开/收起状态。以下是对代码中涉及 localStorage 的部分的详细注释和讲解,帮助更好地理解程序的逻辑:
// 递归渲染树结构
const CubeOutlineTree = ({ cube, initialTree }) => {
// 从 localStorage 获取树的展开/合并状态
const getSavedTreeState = () => {
// 使用 queryUuid 作为键,从 localStorage 获取之前保存的树状态
const savedState = localStorage.getItem(queryUuid);
// 如果获取到保存的状态,则返回该状态, 否则返回初始状态
return savedState ? JSON.parse(savedState) : initialTree;
};
// 使用 useState 管理树的状态,初始值从 localStorage 获取
const [tree, setTree] = useState(getSavedTreeState);
// 切换节点展开/收起状态的函数
const toggleNodeVisibility = (nodes, itemId) => {
return nodes.map(node => {
// 找到对应的节点
if (node.itemId === itemId) {
// 切换该节点的 showChildren 状态,实现展开或收起
return { ...node, showChildren: !node.showChildren };
} else if (node.children) {
// 如果节点有子节点,递归处理子节点
return { ...node, children: toggleNodeVisibility(node.children, itemId) };
}
// 返回未修改的节点
return node;
});
};
// 递归渲染树结构
const renderCubeOutlineTreeItems = (nodes) => {
return nodes.map(node => {
let margin_left = 0; // 默认节点 objType 为 'DimensionRole'
let icon = <NorthEastIcon />; // 默认图标为箭头图标
// 如果节点是 'HierarchyRole' 类型,调整样式和图标
if (node.objType === 'HierarchyRole') {
margin_left = 20;
icon = <DehazeIcon />;
}
// 如果节点是 'MemberRole' 类型,进一步调整样式
if (node.objType === 'MemberRole') {
margin_left = 20 + (node.obj.member.level + 1) * 20; // 增加缩进
icon = <PanoramaFishEyeIcon sx={{ fontSize: '16px' }} />;
}
return (
<Box key={node.itemId}>
<Box sx={{ display: 'flex', alignItems: 'center' }}>
{/* 左侧展开/收起图标 */}
<Box
onClick={() => {
if (node.children.length === 0) return;
// 调用 toggleNodeVisibility 函数切换当前节点状态
const updatedTree = toggleNodeVisibility(tree, node.itemId);
setTree(updatedTree); // 更新状态
// 保持状态到 localStorage 中,使用 queryUuid 作为键
localStorage.setItem(queryUuid, JSON.stringify(updatedTree));
}}
sx={{ marginLeft: `${margin_left}px` }}
>
{/* 根据节点是否有子节点,决定展开/收起图标 */}
{
node.children.length === 0
? <Brightness1TwoToneIcon sx={{ color: '#e0e0e0' }} />
: (node.showChildren ? <KeyboardArrowDownIcon /> : <KeyboardArrowRightIcon />)
}
</Box>
{/* 渲染拖拽树节点 */}
<DraggableTreeNode element={node} icon={icon} />
</Box>
<Box>
{/* 如果当前节点展开,则递归渲染子节点 */}
{node.showChildren && node.children && node.children.length > 0 && renderCubeOutlineTreeItems(node.children)}
</Box>
</Box>
);
});
};
return (
<Box>
<h3>{cube.name}</h3>
{/* 渲染树的节点项 */}
{renderCubeOutlineTreeItems(tree)}
</Box>
);
};
注释讲解:
-
从
localStorage获取树的展开/收起状态:- 在组件初始化时,通过调用
getSavedTreeState函数从localStorage获取先前保存的树结构状态。 - 如果
localStorage中存在保存的状态,则使用它恢复树的状态;如果没有(即首次加载),则使用传入的initialTree初始状态。
- 在组件初始化时,通过调用
-
保存树的状态到
localStorage:- 在每次点击节点进行展开或收起时,调用
toggleNodeVisibility更新树的状态。 - 更新后的状态通过
setTree更新 React 的内部状态,并且通过localStorage.setItem将最新的树状态保存到浏览器的localStorage中。这样,用户在刷新页面后仍然能够看到上次保存的树结构状态。
- 在每次点击节点进行展开或收起时,调用
-
更新节点状态与递归渲染:
toggleNodeVisibility函数根据节点的itemId来切换其子节点是否显示的状态(showChildren)。通过递归方式确保每个节点的子节点状态也能更新。- 通过
renderCubeOutlineTreeItems递归渲染树结构,确保每个节点及其子节点都被正确渲染。
总结:
- 这部分代码的主要功能是处理一个多层级的树结构,通过
localStorage保存和恢复节点的展开/收起状态,从而保持用户的交互体验。通过在用户每次点击展开/收起图标时更新树的状态,并将该状态持久化存储在localStorage中,确保刷新页面后,树的状态能够正确恢复。
浙公网安备 33010602011771号