
本文介绍一种无需服务器、跨页面、可读写的安全方案:利用 Tampermonkey 的 GM_setValue/GM_getValue 配合多域名匹配与脚本职责分离,实现多个独立脚本共用同一份结构化数据(如库存清单)。
本文介绍一种无需服务器、跨页面、可读写的安全方案:利用 tampermonkey 的 `gm_setvalue`/`gm_getvalue` 配合多域名匹配与脚本职责分离,实现多个独立脚本共用同一份结构化数据(如库存清单)。
在实际开发中,尤其是像 Neopets 这类多页面协同操作的场景(例如「安全保管箱」与「快速仓库」两个不同 URL 页面需共用同一套物品清单),开发者常面临一个核心矛盾:既要保持脚本职责单一、逻辑解耦,又要确保数据实时一致。Tampermonkey 默认不支持脚本间直接访问彼此的存储空间,而 localStorage 又受同源策略限制,无法跨域共享——但这并不意味着无解。
✅ 正确路径是:将共享数据层抽象为一个独立的“数据桥接脚本”,该脚本主动声明匹配所有相关页面(如 @match https://www.neopets.com/inventory/safety_deposit* 和 @match https://www.neopets.com/inventory/quickstock*),并统一使用 GM_setValue / GM_getValue 管理 JSON 格式的数据。由于 GM 存储 API 是以用户脚本 ID 为作用域而非页面域,只要多个页面都运行了同一个脚本实例(即同一 @name + 同一 @namespace),它们就能无缝读写同一组键值对。
? 关键实践要点:
用于端到端视频本地化流程的轻量编排器,路由至四个专注子技能——/wjs-transcribing-audio、/wjs-translating-subtitles...
- 必须在元数据头部显式声明 @grant GM_getValue 和 @grant GM_setValue;
- 所有需共享数据的目标页面 URL 都要添加到 @match 列表中;
- 使用 location.href 或 document.URL 动态判断当前上下文,避免逻辑混淆;
- 推荐将数据封装为 JSON 字符串存入 GM 存储(如 GM_setValue('inventory_items', JSON.stringify(items))),读取时 JSON.parse() 还原;
- 若需响应式更新(如脚本 A 修改后脚本 B 自动刷新 UI),可结合 GM_addValueChangeListener 监听变更(注意:监听器仅在注册它的脚本中生效,因此仍建议由桥接脚本统一触发事件或广播自定义 DOM 事件)。
以下是精简可用的共享数据桥接脚本示例(兼容 Chrome/Firefox + TM v4.15+):
// ==UserScript==
// @name Neopets Inventory Hub
// @namespace https://github.com/yourname
// @version 1.0
// @description Centralized JSON inventory storage for multiple TM scripts
// @match https://www.neopets.com/inventory/safety_deposit*
// @match https://www.neopets.com/inventory/quickstock*
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_addValueChangeListener
// ==/UserScript==
(async function () {
'use strict';
// ✅ 初始化默认库存数据(仅首次运行)
const defaultItems = [
{ id: "123", name: "Fire Pteri Egg", quantity: 5 },
{ id: "456", name: "Rainbow Paint Brush", quantity: 1 }
];
const initStorage = async () => {
const stored = await GM_getValue('neopets_inventory');
if (!stored) {
await GM_setValue('neopets_inventory', JSON.stringify(defaultItems));
}
};
// ? 通用读取方法(供其他脚本调用时参考)
window.NeoHub = {
getItems: async () => {
const json = await GM_getValue('neopets_inventory');
return json ? JSON.parse(json) : [];
},
setItems: async (items) => {
await GM_setValue('neopets_inventory', JSON.stringify(items));
}
};
// ? 可选:监听数据变更(用于调试或触发局部刷新)
GM_addValueChangeListener('neopets_inventory', (name, oldValue, newValue, remote) => {
console.log('[NeoHub] Inventory updated:', { old: oldValue, new: newValue, remote });
// 可在此 dispatch CustomEvent 触发其他脚本响应
document.dispatchEvent(new CustomEvent('neopets-inventory-change', { detail: JSON.parse(newValue) }));
});
await initStorage();
})();? 注意事项:
- 不要试图让两个不同 @name 的脚本互相读写 GM 存储——它们彼此隔离;
- 若分发给他人,请确保他们安装的是完全相同的脚本文件(含相同 @name 和 @namespace),否则存储键会因命名空间哈希不同而失效;
- GM_setValue 是异步操作,务必 await;高频写入建议加防抖(如 setTimeout 延迟提交);
- 敏感数据请勿明文存储;如需加密,可集成轻量库(如 CryptoJS)配合密码派生密钥。
通过这种“单点存储、多端接入”的设计,你既能保留原有两套业务脚本的独立性(各自处理页面逻辑),又能获得集中管理、自动同步的 JSON 数据中心——真正兼顾可维护性与功能性。

















