保存与恢复
SkyNote负责文档导出、结构校验和导入,保存位置、时机与失败提示由宿主负责。先从手动快照开始,再根据产品需要接入自动保存或文件归档。
试一次保存与恢复
- 加载画布后,点击“保存临时副本”图标。
- 拖动便签,或双击修改文字。
- 点击“恢复临时副本”,确认内容回到保存时的状态。
此演示使用当前组件内存;不会写浏览器存储,也不会访问用户工作区。离开页面后副本丢失。恢复成功后视口适应内容;重置只重建演示,不覆盖已保存的临时副本。
可复用的快照读写
将下方文件保存为snapshots.ts。SnapshotStorage只要求读写字符串,可接入宿主的同步存储;类型导入不会在加载此工具时初始化浏览器渲染器。
import type { SkyNoteEditor } from '@skynote/editor';
/** 可由localStorage、sessionStorage或测试中的内存对象提供。 */
export interface SnapshotStorage {
getItem(key: string): string | null;
setItem(key: string, value: string): void;
}
export type SnapshotResult = { ok: true } | { ok: false; message: string };
/** 手动保存纯文档快照;不包含历史、视口或媒体二进制。 */
export function saveSnapshot(
editor: SkyNoteEditor<HTMLElement>,
storage: SnapshotStorage,
key: string
): SnapshotResult {
try {
storage.setItem(key, JSON.stringify(editor.exportDocument()));
return { ok: true };
} catch {
return { ok: false, message: '保存失败,存储空间可能不足或不可用。' };
}
}
/** JSON与文档结构分别校验;只有成功导入后才调整视口。 */
export function restoreSnapshot(
editor: SkyNoteEditor<HTMLElement>,
storage: SnapshotStorage,
key: string
): SnapshotResult {
let value: unknown;
try {
const saved = storage.getItem(key);
if (saved === null) return { ok: false, message: '还没有保存的副本。' };
value = JSON.parse(saved);
} catch {
return { ok: false, message: '无法读取副本,存储不可用或JSON已损坏。' };
}
const result = editor.importDocument(value);
if (!result.ok) return { ok: false, message: `文档校验失败:${result.error}` };
editor.fitContent();
return { ok: true };
}JSON解析异常、存储拒绝访问或容量不足都会返回可展示的信息。文档结构错误通过importDocument()结果反馈,调用者必须检查ok;导入失败时不执行后续适配视口操作。
保存到浏览器
与snapshots.ts同目录创建persistence.ts:
import type { SkyNoteEditor } from '@skynote/editor';
import { restoreSnapshot, saveSnapshot, type SnapshotResult } from './snapshots';
// #region save
export function saveToBrowser(editor: SkyNoteEditor<HTMLElement>): SnapshotResult {
// 访问localStorage自身也可能被浏览器策略拒绝。
try {
return saveSnapshot(editor, window.localStorage, 'my-app:canvas:example');
} catch {
return { ok: false, message: '浏览器未允许访问本地存储。' };
}
}
// #endregion save
// #region restore
export function restoreFromBrowser(editor: SkyNoteEditor<HTMLElement>): SnapshotResult {
try {
return restoreSnapshot(editor, window.localStorage, 'my-app:canvas:example');
} catch {
return { ok: false, message: '浏览器未允许访问本地存储。' };
}
}
// #endregion restore
// #region viewport
export function rememberViewport(editor: SkyNoteEditor<HTMLElement>): () => void {
const viewport = { ...editor.viewport };
return () => editor.applyInitialView('preserve', viewport);
}
// #endregion viewport在明确的保存按钮中调用saveToBrowser(editor),打开文档时或恢复按钮中调用restoreFromBrowser(editor),并将失败结果显示给使用者。这两个函数仅在客户端调用。实际项目应把存储键按应用、用户和文档区分,避免同源页面互相覆盖。
localStorage适合小型、低频的纯文档快照,不等于生产级灾备方案。大文档、图片和连续编辑应使用合适的宿主存储,并设计写入失败、关闭页面和多标签页冲突处理。
快照不包含什么
| 内容 | 处理方式 |
|---|---|
| 节点、连线、资产元数据引用 | 包含在导出的文档中 |
| 视口、选区、工具和主题 | 会话状态,由宿主单独保存;rememberViewport仅展示同次会话的视口恢复 |
| 撤销重做栈 | 不包含在普通文档JSON中,不将恢复快照视为完整历史恢复 |
| 图片等媒体二进制 | 由AssetAdapter管理,JSON中的assetId不是文件本身 |
导入带图片的文档时,需要对应资产可用;缺失或校验失败应提示用户,不能静默忽略。自定义节点需要先装配相应插件。
后续接入自动保存
可通过onCommit接收增量补丁,或订阅文档变化后调度保存;监听回调只记录变化,不同步提交新的文档事务。不要在拖动或文字输入的每一步都导出整份文档。需要合并保存时,应设置写入队列、脏标记、错误重试和卸载清理,避免后来的状态被较早任务覆盖。
本页提供的是手动快照教程,不承诺多标签页协调、断电恢复、云同步或图片归档。