Files
vue-desktop/.qoder/repowiki/zh/content/响应式布局系统/图标重排与持久化.md
2025-09-24 16:43:10 +08:00

7.5 KiB
Raw Blame History

图标重排与持久化

**Referenced Files in This Document ** - [useDesktopContainerInit.ts](file://src/ui/desktop-container/useDesktopContainerInit.ts) - [DesktopContainer.vue](file://src/ui/desktop-container/DesktopContainer.vue) - [IDesktopAppIcon.ts](file://src/ui/types/IDesktopAppIcon.ts)

目录

  1. appIconsRef的创建过程
  2. localStorage数据同步机制
  3. 网格变化监听与重排响应
  4. rearrangeIcons算法详解
  5. 布局状态持久化策略

appIconsRef的创建过程

appIconsRef 是一个 Vue 响应式引用,用于管理桌面图标的布局状态。其创建过程始于 useDesktopContainerInit 函数的调用,该函数接收容器选择器字符串作为参数并初始化核心布局逻辑。

在初始化过程中,系统首先从 localStorage 中读取键为 desktopAppIconInfo 的存储项,尝试恢复之前保存的图标位置信息。若存在历史数据,则解析为 oldAppIcons 数组;否则使用空数组作为默认值。随后,系统遍历当前可用的应用程序列表(appInfos),为每个应用创建对应的桌面图标对象。

对于每个新生成的图标系统优先检查是否存在同名的历史图标记录。如果存在则继承其坐标x, y若不存在则根据当前网格的行列数按索引自动分配初始坐标

  • 列坐标 x = 当前索引 % 行数 + 1
  • 行坐标 y = floor(当前索引 / 行数) + 1

最终,这些图标数据被封装为响应式引用 appIconsRef,供视图层绑定使用。

Section sources

localStorage数据同步机制

系统通过双向数据绑定机制实现 appIconsReflocalStorage 的实时同步。当用户对桌面图标进行拖拽、重排等操作导致布局变更时Vue 的响应式系统会触发相应的监听器,将最新状态持久化到本地存储中。

具体而言,系统注册了一个针对 appIconsRef.valuewatch 监听器。每当图标数组内容发生变化(如新增、删除或位置调整),该监听器便会执行回调函数,将更新后的 appIcons 数组序列化为 JSON 字符串,并通过 localStorage.setItem('desktopAppIconInfo', ...) 方法写入浏览器本地存储。

此机制确保了用户在刷新页面或重新打开应用后,能够恢复上次关闭时的桌面布局,实现了跨会话的个性化配置记忆功能。

Section sources

网格变化监听与重排响应

为了适应不同屏幕尺寸和窗口大小的变化,系统利用 ResizeObserver API 实时监测桌面容器的尺寸变动,并动态计算最优的网格列数(colCount)和行数(rowCount)。当这些参数发生改变时,系统需要智能地重新排列所有图标以避免重叠或溢出。

为此,系统设置了一个复合监听器 watch(() => [gridTemplate.colCount, gridTemplate.rowCount], ...), 专门监控 colCountrowCount 的联合变化。一旦检测到新的网格维度,监听器立即调用 rearrangeIcons 函数,传入当前图标列表及新的行列限制,执行自动重排逻辑。

该监听器包含优化判断:若新旧行列数完全一致,则直接返回,避免不必要的重排计算,提升性能效率。

Section sources

rearrangeIcons算法详解

rearrangeIcons 函数是整个图标管理系统的核心算法,负责处理图标冲突、寻找空闲位置以及管理超出可视范围的图标。其输入为原始图标数组和目标网格的最大行列数,输出为包含正常显示图标和隐藏图标的结构体。

冲突检测与占用标记

算法首先创建一个 Set<string> 类型的 occupied 集合,用于记录已被占用的网格单元。通过辅助函数 key(x, y) 将二维坐标转换为唯一字符串标识(如 "1,2"),实现高效的哈希查找。

分阶段处理流程

  1. 第一阶段:保留有效位置

    • 遍历所有图标,筛选出位于当前网格范围内的图标(即 x ≤ maxCol && y ≤ maxRow
    • 检查目标位置是否已被占用,若未占用则将其加入结果数组 appIcons 并标记为已占用
    • 对于位置无效或冲突的图标,则暂存至临时数组 temp
  2. 第二阶段:填补空位

    • 遍历 temp 数组中的待安置图标
    • 若当前已放置图标数量小于网格总容量(maxCol * maxRow),则从左上角 (1,1) 开始逐行扫描,寻找第一个空闲位置进行安置
    • 一旦找到合适位置,立即跳出内层循环,继续处理下一个图标
  3. 第三阶段:处理溢出图标

    • 若网格已满且仍有剩余图标无法安置,则将其归类至 hideAppIcons 数组
    • 这些图标将在 UI 层面被隐藏,防止界面混乱
flowchart TD
Start([开始重排]) --> ValidatePosition["验证图标位置有效性"]
ValidatePosition --> InRange{"是否在网格范围内?"}
InRange --> |是| CheckOccupied["检查位置是否被占用"]
InRange --> |否| ToTemp["加入临时数组 temp"]
CheckOccupied --> IsFree{"位置空闲?"}
IsFree --> |是| PlaceIcon["放置图标并标记占用"]
IsFree --> |否| ToTemp
PlaceIcon --> NextIcon["处理下一个图标"]
ToTemp --> NextIcon
NextIcon --> AllProcessed{"所有图标处理完毕?"}
AllProcessed --> |否| ValidatePosition
AllProcessed --> |是| FillEmpty["填补空位"]
FillEmpty --> HasSpace{"仍有空位?"}
HasSpace --> |是| FindSlot["从(1,1)开始寻找空位"]
HasSpace --> |否| HideExcess["隐藏超出图标"]
FindSlot --> CanPlace{"能否放置?"}
CanPlace --> |是| UpdateAppIcons["更新 appIcons 数组"]
CanPlace --> |否| HideExcess
UpdateAppIcons --> MoreTemp{"temp 数组为空?"}
MoreTemp --> |否| FillEmpty
MoreTemp --> |是| ReturnResult["返回结果: appIcons + hideAppIcons"]
HideExcess --> ReturnResult

**Diagram sources **

Section sources

布局状态持久化策略

系统的布局持久化策略建立在 Vue 的响应式系统与浏览器本地存储的协同工作之上。appIconsRef 作为单一数据源Single Source of Truth集中管理所有图标的坐标信息。任何对图标的修改操作无论是用户交互还是程序逻辑都会反映到该引用上。

通过 watch 监听器,系统实现了从内存状态到持久化存储的单向同步。这种设计具有以下优势:

  • 自动同步:无需手动调用保存方法,所有变更自动记录
  • 原子性保证:每次写入都是完整的数组快照,避免部分更新导致的数据不一致
  • 跨会话恢复:页面刷新后可通过 localStorage.getItem('desktopAppIconInfo') 重建初始状态
  • 容错处理:使用 JSON.parse(... || '[]') 确保解析失败时返回安全默认值

该策略构成了完整的“读取→运行→修改→保存”闭环,保障了用户体验的一致性和数据的安全性。

Section sources