对代码中涉及 `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
中,确保刷新页面后,树的状态能够正确恢复。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话