tab页跨页面存储信息

1. 文档说明

本文档描述业务 iframe 与宿主父页面之间的存储通信协议。iframe 不直接操作宿主页面的业务存储,而是通过浏览器 postMessage API 请求父页面代为保存或查询数据。适用场景:
  • 子页面运行在 <iframe> 中;
  • 父页面负责统一管理 iframe 数据;
  • 数据最终写入浏览器 localStorage
说明:原 HTML 中提供了 iframe 侧的发送和接收逻辑;父页面的消息处理器需要由接入方实现。

2. 通信模型

2.1 通信方向

方向API用途
iframe → 父页面window.parent.postMessage(message, targetOrigin)发起存储或查询请求
父页面 → iframewindow.postMessage(message, targetOrigin)返回处理结果
iframe 通过以下方式监听父页面回复:
window.addEventListener('message', handler)

2.2 前置握手消息

iframe 加载完成后会主动向父页面发送:
{ "hello": true }
该消息用于通知父页面 iframe 已加载。原 Demo 未定义对应响应,父页面可按需记录或忽略。

2.3 消息格式约定

所有消息均为 JavaScript 对象,通过 postMessage 传递。协议使用 type 字段区分消息类型。请求和响应中的 key 应保持一致。

3. 存储数据

3.1 请求

消息类型:set-storage
window.parent.postMessage({ type: 'set-storage', key: 'userName', value: '张三' }, '*')
字段说明:
字段类型必填说明
typestring固定值 "set-storage"
keystring存储键名,必须符合第 5 节校验规则
valueany要存储的值,可为字符串、数字、对象、数组等

3.2 成功响应

消息类型:storage-set
{ "type": "storage-set", "key": "userName", "success": true, "message": "userName stored successfully" }
字段类型说明
typestring固定值 "storage-set"
keystring请求中的键名
successboolean是否存储成功;成功时为 true
messagestring处理结果说明

3.3 失败响应

失败时仍返回 type: "storage-set",通过 success: false 表示失败,message 返回具体原因。例如:
{ "type": "storage-set", "key": "userName", "success": false, "message": "value too large, max 100KB" }

4. 查询数据

4.1 请求

消息类型:get-storage
window.parent.postMessage({ type: 'get-storage', key: 'userName' }, '*')
字段说明:
字段类型必填说明
typestring固定值 "get-storage"
keystring要查询的键名

4.2 查询响应

消息类型:storage-get

存在数据

{ "type": "storage-get", "key": "userName", "exists": true, "value": "张三" }

不存在数据

{ "type": "storage-get", "key": "missingKey", "exists": false, "value": null, "message": "not found" }
字段类型说明
typestring固定值 "storage-get"
keystring请求中的键名
existsboolean是否存在该键;不存在时为 false
valueany存在时返回存储值;不存在时为 null
messagestring不存在时通常为 "not found";存在时可不返回

5. 数据校验与容量限制

父页面在处理 set-storage 请求时应执行以下校验:
校验项限制失败时的 message
Key 类型及必填key 必须存在且为 stringinvalid key: key is required and must be a string
Key 字符仅允许 A-Za-z0-9_.-invalid key: only letters, numbers, underscore, dot, hyphen allowed
Key 长度最长 64 个字符key too long, max 64 chars
单个 Value 大小最大 100KBvalue too large, max 100KB
总存储容量所有 iframe 数据合计最大 2MBstorage quota exceeded, max 2MB total for iframe data
Key 数量最多 50 个too many keys, max 50 keys allowed
localStorage 异常浏览器存储空间不足等异常storage failed, localStorage may be full
Key 校验可参考:
const KEY_PATTERN = /^[A-Za-z0-9_.-]+$/ const valid = typeof key === 'string' && key.length <= 64 && KEY_PATTERN.test(key)
所有 iframe 数据写入 localStorage 时使用 iframe_ 前缀,以便与宿主项目其他数据隔离。例如:
iframe_userName

6. iframe 侧接入示例

function requestSet(key, value) { if (window.parent === window) { throw new Error('当前页面不在 iframe 中') } window.parent.postMessage({ type: 'set-storage', key, value }, '*') } function requestGet(key) { if (window.parent === window) { throw new Error('当前页面不在 iframe 中') } window.parent.postMessage({ type: 'get-storage', key }, '*') } window.addEventListener('message', (event) => { const data = event.data || {} if (data.type === 'storage-set') { if (data.success) { console.log('存储成功:', data.key) } else { console.error('存储失败:', data.message) } } if (data.type === 'storage-get') { if (data.exists) { console.log('查询结果:', data.value) } else { console.log('数据不存在:', data.message || 'not found') } } })

7. 父页面接入要求

父页面需要监听 message 事件,识别 set-storageget-storage,完成校验、读写 localStorage,并将结果发回触发请求的 iframe(通常使用 event.source.postMessage)。建议处理流程如下:
  1. 校验消息来源 event.originevent.source,确认来自受信任 iframe。
  2. 校验 event.data 是否为对象,并检查 typekey 等字段。
  3. set-storage 执行 key、value、容量和数量校验。
  4. 使用 iframe_ 前缀读写数据。
  5. 按协议返回 storage-setstorage-get 响应。
父页面回复示例:
window.addEventListener('message', (event) => { const data = event.data || {} if (!event.source || typeof data !== 'object') return if (data.type === 'get-storage') { const storageKey = `iframe_${data.key}` const raw = localStorage.getItem(storageKey) const response = raw === null ? { type: 'storage-get', key: data.key, exists: false, value: null, message: 'not found' } : { type: 'storage-get', key: data.key, exists: true, value: JSON.parse(raw) } event.source.postMessage(response, event.origin) } })
上述代码仅展示通信方式。生产环境还应补充完整的来源白名单、异常捕获、序列化失败处理和容量统计。

8. 安全注意事项

原 Demo 使用 postMessage(data, '*'),便于本地演示,但生产环境不建议继续使用通配符:
  • 发送时将 '*' 替换为明确的父页面 Origin;
  • 接收时校验 event.origin 是否在允许列表中;
  • 校验 event.source 是否为预期 iframe 的 contentWindow
  • 不要把密码、Token、身份证号等高敏感信息直接写入 localStorage
  • JSON.parseJSON.stringifylocalStorage 操作进行异常处理。

9. 错误处理建议

调用方应以响应中的 type 作为第一层判断,以 successexists 作为业务结果判断,以 message 作为日志和排查依据。建议不要仅通过 message 文案判断成功失败,因为文案可能在后续版本中调整。

10. 兼容性与边界说明

  • 通信依赖浏览器 window.postMessagemessage 事件。
  • 页面直接打开、未嵌入 iframe 时,window.parent === window,无法向父页面发送请求。
  • value 标注为 any,但跨窗口传输和 localStorage 持久化通常需要进行结构化克隆或 JSON 序列化;父页面应统一约定序列化规则。
  • 原 HTML 未定义请求 ID、超时、重试和并发关联机制。如存在并发请求同一 key 的场景,建议后续增加 requestId 字段。

示例demo

iframe-storage-demo.html
10.4 KB
2026-09-04