7.5 KiB
图标重排与持久化
**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)目录
appIconsRef的创建过程
appIconsRef 是一个 Vue 响应式引用,用于管理桌面图标的布局状态。其创建过程始于 useDesktopContainerInit 函数的调用,该函数接收容器选择器字符串作为参数并初始化核心布局逻辑。
在初始化过程中,系统首先从 localStorage 中读取键为 desktopAppIconInfo 的存储项,尝试恢复之前保存的图标位置信息。若存在历史数据,则解析为 oldAppIcons 数组;否则使用空数组作为默认值。随后,系统遍历当前可用的应用程序列表(appInfos),为每个应用创建对应的桌面图标对象。
对于每个新生成的图标,系统优先检查是否存在同名的历史图标记录。如果存在,则继承其坐标(x, y);若不存在,则根据当前网格的行列数按索引自动分配初始坐标:
- 列坐标 x = 当前索引 % 行数 + 1
- 行坐标 y = floor(当前索引 / 行数) + 1
最终,这些图标数据被封装为响应式引用 appIconsRef,供视图层绑定使用。
Section sources
localStorage数据同步机制
系统通过双向数据绑定机制实现 appIconsRef 与 localStorage 的实时同步。当用户对桌面图标进行拖拽、重排等操作导致布局变更时,Vue 的响应式系统会触发相应的监听器,将最新状态持久化到本地存储中。
具体而言,系统注册了一个针对 appIconsRef.value 的 watch 监听器。每当图标数组内容发生变化(如新增、删除或位置调整),该监听器便会执行回调函数,将更新后的 appIcons 数组序列化为 JSON 字符串,并通过 localStorage.setItem('desktopAppIconInfo', ...) 方法写入浏览器本地存储。
此机制确保了用户在刷新页面或重新打开应用后,能够恢复上次关闭时的桌面布局,实现了跨会话的个性化配置记忆功能。
Section sources
网格变化监听与重排响应
为了适应不同屏幕尺寸和窗口大小的变化,系统利用 ResizeObserver API 实时监测桌面容器的尺寸变动,并动态计算最优的网格列数(colCount)和行数(rowCount)。当这些参数发生改变时,系统需要智能地重新排列所有图标以避免重叠或溢出。
为此,系统设置了一个复合监听器 watch(() => [gridTemplate.colCount, gridTemplate.rowCount], ...), 专门监控 colCount 和 rowCount 的联合变化。一旦检测到新的网格维度,监听器立即调用 rearrangeIcons 函数,传入当前图标列表及新的行列限制,执行自动重排逻辑。
该监听器包含优化判断:若新旧行列数完全一致,则直接返回,避免不必要的重排计算,提升性能效率。
Section sources
rearrangeIcons算法详解
rearrangeIcons 函数是整个图标管理系统的核心算法,负责处理图标冲突、寻找空闲位置以及管理超出可视范围的图标。其输入为原始图标数组和目标网格的最大行列数,输出为包含正常显示图标和隐藏图标的结构体。
冲突检测与占用标记
算法首先创建一个 Set<string> 类型的 occupied 集合,用于记录已被占用的网格单元。通过辅助函数 key(x, y) 将二维坐标转换为唯一字符串标识(如 "1,2"),实现高效的哈希查找。
分阶段处理流程
-
第一阶段:保留有效位置
- 遍历所有图标,筛选出位于当前网格范围内的图标(即
x ≤ maxCol && y ≤ maxRow) - 检查目标位置是否已被占用,若未占用则将其加入结果数组
appIcons并标记为已占用 - 对于位置无效或冲突的图标,则暂存至临时数组
temp
- 遍历所有图标,筛选出位于当前网格范围内的图标(即
-
第二阶段:填补空位
- 遍历
temp数组中的待安置图标 - 若当前已放置图标数量小于网格总容量(
maxCol * maxRow),则从左上角(1,1)开始逐行扫描,寻找第一个空闲位置进行安置 - 一旦找到合适位置,立即跳出内层循环,继续处理下一个图标
- 遍历
-
第三阶段:处理溢出图标
- 若网格已满且仍有剩余图标无法安置,则将其归类至
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