
大致可以这么理解:
1️⃣ 普通脚本(新建普通脚本)
-
运行位置:在网页里运行,相当于给某个页面"塞一段 JS"
-
触发方式:当你打开/刷新匹配的网址时自动注入执行
-
能做的事:
- 操作当前页面 DOM(增删元素、自动点击、填表单......)
- 监听用户操作
- 跟页面里的 JS 互动
-
典型用途:页面改造、自动化操作、加按钮、加 iframe 等
你现在写的"在某个系统页面插 iframe"这种,就是用 普通脚本。
2️⃣ 后台脚本(新建后台脚本)
-
运行位置:扩展的后台环境,不依附具体网页
-
触发方式:浏览器启动、扩展加载时就可以常驻;也可以被其它脚本消息唤起
-
特点:
- 不直接操作任何网页 DOM
- 适合做全局逻辑:统一请求、数据中转、长连接、全局状态、与浏览器 API 交互
- 可以和普通脚本通过
GM_*或消息通信协作
-
典型用途:
- 做一个"总控中枢":管理多个页面脚本的配置、共享登录状态
- 长连接 / WebSocket 客户端
- 统一的任务队列、请求转发、存储
你可以理解为:像浏览器扩展的 background.js。
3️⃣ 定时脚本(新建定时脚本)
-
运行位置:也是在扩展环境中运行,不依附具体网页
-
触发方式:按你在脚本设置里配置的时间/间隔自动执行
-
特点:
- 不需要打开某个页面也能跑
- 每次到点就执行一次脚本的入口函数
-
典型用途:
- 定时请求某个接口(签到、拉取数据)
- 定时发通知、检测状态
- 配合后台脚本/存储做"定时任务中心"
简单记忆版
- 普通脚本:👉"绑在网页上的脚本",随页面一起跑,最适合 DOM 操作。
- 后台脚本:👉"常驻后台的服务脚本",做全局逻辑、通信、长连接。
- 定时脚本:👉"闹钟脚本",按时间点自动执行任务。
🍎🍎🍎🍎 Chrome扩展后台脚本不完全指南:从Manifest V2到V3版本,background.js的运行机制有哪些变化?**

🍎🍎🍎🍎GPT回答: 定时拉接口、跨多个页面共享状态、自动操作页面。帮我画一个"普通脚本 + 后台脚本 + 定时脚本"的组合结构。
那我给你搭一个「三合一」的脚本系统架构,直接围绕你说的三件事:
- ✅ 定时拉接口
- ✅ 跨多个页面共享状态
- ✅ 进入页面后自动操作 DOM
一、整体结构图(文字版)
css
┌───────────────────────────┐
│ 定时脚本(Timer) │
│ - 每 X 分钟调用接口 │
│ - 处理/整理数据 │
│ - 写入全局存储 │
└─────────────┬─────────────┘
│ GM_setValue / 存储
▼
┌──────────────────────────────┐
│ 脚本猫全局存储/GM_xxx │
│ - lastFetchTime │
│ - apiData │
│ - userConfig │
└─────────────▲───────────────┘
│ GM_getValue / 监听变化
┌───────────────┴────────────────────┐
│ │
┌───────┴────────────────┐ ┌──────────┴──────────────┐
│ 后台脚本(Background)│ │ 普通脚本(Page Script)│
│ - 作为中枢服务 │ │ - 匹配具体系统页面 │
│ - 维护内存缓存 │ │ - 读取全局数据 │
│ - 处理复杂逻辑/长连接 │ │ - 根据数据自动操作DOM │
│ - 接收页面脚本消息 │ │ - 向后台脚本请求服务 │
└────────────────────────┘ └─────────────────────────┘
核心思想:
- 定时脚本 专心负责:定时拉接口 + 写入全局状态
- 后台脚本 做"中控":读写存储、处理复杂逻辑、对外提供服务
- 普通脚本 只管:在页面里读状态 + 操作 DOM
二、三个需求是怎么串起来的?
1. 定时拉接口 ------ 用「定时脚本」
**触发:**你在脚本猫里设置每 5 分钟 / 每小时运行一次。
流程:
- 定时脚本触发 → 通过
GM_xmlhttpRequest/fetch调你的接口。 - 把返回数据整理成你想要的结构。
- 用
GM_setValue('apiData', data)存到全局。 - 顺便存个时间:
GM_setValue('lastFetchTime', Date.now())。
这样就算浏览器里没有开具体页面,数据也会一直"被喂新"。
2. 跨多个页面共享状态 ------ 用「全局存储 + 后台脚本」
多个页面 + 多个普通脚本,如何共享同一份数据?
-
所有脚本(定时、后台、普通)都用 同一个脚本猫存储空间(同一个"脚本项目")。
-
统一用
GM_getValue/GM_setValue读写,比如:apiData:最近一次接口数据lastFetchTime:更新时间userConfig:你在配置页改的配置(比如"开关""阈值")
后台脚本 做两件事:
-
缓存 + 快速响应:
- 在启动时读取一次
GM_getValue('apiData')放到内存。 - 普通脚本通过消息(比如 GM 通信或 ScriptCat 自带 API)问后台要数据,后台直接从内存/存储里回。
- 在启动时读取一次
-
监听变化:
- 使用
GM_addValueChangeListener('apiData', ...) - 一旦定时脚本更新了
apiData,后台脚本能第一时间感知,有需要时再推送给页面脚本(可选)。
- 使用
这样你在 A 页面用到这份数据,B 页面、C 页面也能读同一套最新的内容。
3. 自动操作页面 ------ 用「普通脚本」
普通脚本挂在具体业务页面上,比如:
- 系统的订单列表页
- 工单详情页
- 通话界面等
流程:
-
页面加载完成 → 普通脚本启动。
-
先从全局存储中读取数据:
iniconst data = GM_getValue('apiData'); -
如果需要更复杂的处理(比如多接口组合、数据清洗),可以:
- 直接给后台脚本发消息:
request('processData', { pageInfo }) - 后台脚本返回处理好的结果。
- 直接给后台脚本发消息:
-
拿到数据后,开始 DOM 自动化:
- 根据接口返回的数据,自动填表、自动点击、自动切换 tab......
- 数据不够新时,也可以请求后台脚本「临时拉一次接口」。
三、三个脚本的简单骨架示例(伪代码)
1️⃣ 定时脚本(拉接口 + 写入状态)
javascript
// ==UserScript==
// @name 定时拉接口脚本
// @namespace your-namespace
// @version 1.0
// @description 定时请求接口并更新全局数据
// @grant GM_setValue
// @grant GM_xmlhttpRequest
// ==/UserScript==
(async function () {
// 这里是定时任务触发时的主函数
const url = 'https://api.example.com/data';
GM_xmlhttpRequest({
method: 'GET',
url,
onload: (res) => {
try {
const data = JSON.parse(res.responseText);
// 处理数据,比如只保留关键字段
const simplified = {
updatedAt: Date.now(),
list: data.items || [],
};
GM_setValue('apiData', simplified);
GM_setValue('lastFetchTime', Date.now());
} catch (e) {
console.error('解析接口数据失败', e);
}
},
onerror: (err) => {
console.error('接口请求失败', err);
},
});
})();
定时逻辑由脚本猫"定时脚本"的配置控制,不需你写 setInterval。
2️⃣ 后台脚本(中枢服务)
typescript
// ==UserScript==
// @name 后台中枢脚本
// @namespace your-namespace
// @version 1.0
// @description 统一管理全局状态,对普通脚本提供服务
// @grant GM_getValue
// @grant GM_addValueChangeListener
// ==/UserScript==
// 内存缓存
let apiCache = GM_getValue('apiData', null);
// 监听存储变化(定时脚本更新时会触发)
GM_addValueChangeListener('apiData', (name, oldValue, newValue, remote) => {
apiCache = newValue;
console.log('apiData 已更新:', newValue);
});
// 提供一个简单的消息处理(ScriptCat 有自己的消息 API 可以用)
// 这里伪代码,表示"接收页面脚本的请求"
window.addEventListener('message', (e) => {
const { type, requestId } = e.data || {};
if (type === 'getApiData') {
// 回给页面脚本(同样用 postMessage 或 ScriptCat 自带 GM 通信)
window.postMessage({
type: 'getApiDataResult',
requestId,
data: apiCache,
});
}
});
实际通信 API 你可以用 ScriptCat 提供的方式,比如
GM_sendMessage/ 自带的ScriptCat通信封装。
3️⃣ 普通脚本(页面自动化)
javascript
// ==UserScript==
// @name 页面自动操作脚本
// @namespace your-namespace
// @version 1.0
// @description 在系统页面中自动操纵 DOM
// @match https://system.example.com/*
// @grant GM_getValue
// ==/UserScript==
(function () {
'use strict';
// 简单场景:直接从全局存储里读
const apiData = GM_getValue('apiData', null);
console.log('当前全局数据:', apiData);
// 等页面加载完后再操作 DOM
window.addEventListener('load', () => {
if (!apiData || !apiData.list || apiData.list.length === 0) {
console.log('暂无数据,不自动操作');
return;
}
// 举例:根据某个字段自动点击按钮
autoClickByData(apiData);
});
function autoClickByData(data) {
// 这里写你的页面逻辑,比如:
// 1. 找到需要处理的行
// 2. 判断是否满足条件
// 3. 触发点击 / 填写输入框等
const buttons = document.querySelectorAll('.process-btn');
data.list.forEach((item, idx) => {
const btn = buttons[idx];
if (!btn) return;
if (item.needProcess) {
btn.click();
}
});
}
})();
如果你想走 "普通脚本向后台脚本要数据" 的路线,可以在普通脚本中:
- 给后台脚本发
postMessage: {type: 'getApiData', requestId} - 监听
message获取getApiDataResult再操作 DOM。
四、如何落地到你的项目?
你可以按这个思路拆三个"脚本项目":
-
定时脚本:
- 只写请求接口 +
GM_setValue。 - 在脚本猫的"定时任务"里设 每 X 分钟运行一次。
- 只写请求接口 +
-
后台脚本:
- 不匹配任何 URL(或只在
*下启动)。 - 负责监听
GM_addValueChangeListener+ 消息通信。
- 不匹配任何 URL(或只在
-
一个或多个普通脚本:
- 分别匹配不同系统页面(列表页、详情页等)。
- 统一从全局状态/后台脚本拿数据 → 自动操作 DOM。
如果你愿意,可以告诉我:
- 你接口的大致返回结构(字段名、列表在哪个字段下)
- 一个具体的系统页面 URL / 页面结构(大概有哪些按钮 / 列表)
我可以直接给你「可复制进脚本猫就能跑」的完整三脚本示例,帮你串起来。