对代码中涉及 `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>
    );
};

注释讲解:

  1. localStorage 获取树的展开/收起状态:

    • 在组件初始化时,通过调用 getSavedTreeState 函数从 localStorage 获取先前保存的树结构状态。
    • 如果 localStorage 中存在保存的状态,则使用它恢复树的状态;如果没有(即首次加载),则使用传入的 initialTree 初始状态。
  2. 保存树的状态到 localStorage

    • 在每次点击节点进行展开或收起时,调用 toggleNodeVisibility 更新树的状态。
    • 更新后的状态通过 setTree 更新 React 的内部状态,并且通过 localStorage.setItem 将最新的树状态保存到浏览器的 localStorage 中。这样,用户在刷新页面后仍然能够看到上次保存的树结构状态。
  3. 更新节点状态与递归渲染:

    • toggleNodeVisibility 函数根据节点的 itemId 来切换其子节点是否显示的状态(showChildren)。通过递归方式确保每个节点的子节点状态也能更新。
    • 通过 renderCubeOutlineTreeItems 递归渲染树结构,确保每个节点及其子节点都被正确渲染。

总结:

  • 这部分代码的主要功能是处理一个多层级的树结构,通过 localStorage 保存和恢复节点的展开/收起状态,从而保持用户的交互体验。通过在用户每次点击展开/收起图标时更新树的状态,并将该状态持久化存储在 localStorage 中,确保刷新页面后,树的状态能够正确恢复。

posted on 2024-11-30 10:11  及途又八  阅读(42)  评论(0)    收藏  举报

导航