JS pane:按需运行的脚本,不会每次访问都自动运行
一条 JustZix 的 JS 规则在 URL 匹配时自动运行。这对那些总该工作的事情很棒 —— 自动跳过 cookie 横幅、自定义快捷键。但有些脚本是破坏性的:「清空购物车」、「删除邮件草稿」、「重置表单」。这些你不想自动运行。你想只在你想要时点击 ▶。这就是 JS pane(v2.13.56+)。
三种 JS 窗口 —— 哪个干哪个活
| 窗口类型 | 何时执行 | 使用场景 |
|---|---|---|
| JS 规则 | 每次加载匹配 URL 时自动执行 | 跳过 cookie、自定义快捷键、GTM 日志器 |
| JS Console | 每次 Ctrl+Enter = 一次新求值 | 临时 REPL、一次性检查 |
| JS pane | 仅在 Ctrl+Enter / 点击 ▶ 时 | 持久代码、破坏性动作、批量操作 |
一个 JS pane 看上去几乎像 CSS pane(文本框、可拖动、彩色圆点),但头部多了一个 ▶ Run 按钮。代码活在文本框里,从不自动执行 —— 唯一的例外是刷新后的恢复(如果 F5 之前 sessionStorage 里有东西,JustZix 会重新执行它来恢复刷新前的状态)。
首次使用
- JustZix 选项 → 文件夹/分组/规则 → 「窗口」→ 「+ JS pane」。
- 名字:「清空购物车」,颜色:琥珀色(默认 #D65D0E)。
- 访问
shop.com/cart。pane 出现在右上角,带头部(「• 清空购物车 [▶]」)和一个空文本框。 - 输入:
document.querySelectorAll('.cart-item .remove-btn') .forEach(btn => btn.click()); - Ctrl+Enter(或点击 ▶)。所有「移除」按钮被点击。
脏状态 —— 你在视觉上知道有改动
在你打字 / 修改代码之后,只要还没执行它(或回到上次执行的版本),Run 按钮就显示「脏」状态(带一个自定义的 runColor —— 从 v2.13.64 起你可以选自己的)。这是个视觉信号:「你有未执行的改动」。
点击 ▶ → 代码被执行,脏状态消失。把文本框还原到一个先前的值 → 脏状态重新出现。JustZix 把当前内容和 el.dataset.jzLastRun 作比较。
错误浮层 —— 无需开着 DevTools
当求值抛出异常时,pane 底部出现一条红色横条(.jz-pane-error):
JS 错误: Cannot read properties of null (reading 'click')
用修正后的代码再次点击 ▶ → 错误消失。无需 F12 开开关关。对于异步错误(一个抛错的 setTimeout(...))浮层捕获不到 —— 已知的局限,异步错误要通过 DevTools 或 JustZix 的 JS Console 来追踪。
持久 vs 短暂 —— 哪种场景
JS pane 的内容按标签页持久化在 sessionStorage['jz_pane_{id}_content'] 里。后果:
- F5 / 标签页内导航 —— pane 重新挂载,文本框重新读取代码,自动恢复会重新执行它。刷新后的页面状态 = 第一次执行后的状态。
- 同一域名上的新标签页 —— pane 显示为空。每个标签页有自己的 sessionStorage。
- 关闭标签页 —— pane 的内容丢失。pane 定义本身(名字、颜色、作用域)仍保留,因为它在 chrome.storage 里,但文本框变回空。
如果你想要永久的代码(关掉标签页之后也在)—— 那它不是 pane,是一条 JS 规则。pane = 带 Run 按钮的草稿本。
使用场景 1 —— 与状态相关的破坏性动作
清理商店后台面板。动作「从购物车移除所有演示商品」:
// 仅在你点击 ▶ 时运行。自动运行 = 灾难。
if (!location.href.includes('/admin/demo')) {
throw new Error('仅限 /admin/demo');
}
const rows = document.querySelectorAll('tr.product');
console.log(`正在移除 ${rows.length} 个商品...`);
for (const row of rows) {
await fetch('/api/products/' + row.dataset.id, { method: 'DELETE' });
row.remove();
}
console.log('完成。');
防线:URL 守卫 + pane 名字「CLEANUP DEMO」+ 琥珀色圆点。很难误操作。
使用场景 2 —— 批量操作
50 个用户要被标记为「已验证」。UI 只允许逐个用户点击。JS pane:
const rows = document.querySelectorAll('.user-row:not(.verified)');
let count = 0;
for (const row of rows) {
row.querySelector('.btn-verify')?.click();
await new Promise(r => setTimeout(r, 200)); // 限速,免得 API 抗议
count++;
}
console.log(`${count} 个用户已验证。`);
点一下 ▶,50 个用户。200 毫秒 sleep 避免淹没 API。比那个并不存在的真正批量端点快三倍。
使用场景 3 —— 脚本化演示
你在向客户演示「添加 3 件商品 + 进入结账 + 填入测试数据」的流程。每次 30 秒。一段 pane 脚本 2 秒内全部搞定:
// 演示流程
[1, 2, 3].forEach(i => document.querySelector(`[data-product-id="${i}"] .add-btn`)?.click());
await new Promise(r => setTimeout(r, 500));
document.querySelector('.checkout-btn').click();
await new Promise(r => setTimeout(r, 1000));
Object.entries({
email: 'demo@example.com', name: 'Demo', address: 'Test 1'
}).forEach(([k, v]) => {
const el = document.querySelector(`[name="${k}"]`);
if (el) { el.value = v; el.dispatchEvent(new Event('input', { bubbles: true })); }
});
客户看到一个「自动驾驶」式的流程。专业。无需实时打字。
坑
- 异步错误不出现在浮层里 ——
setTimeout(() => { throw new Error('x') }, 100)最终落进全局控制台,而不是 pane 的错误框。变通:在异步函数里包一层 try/catch。 - 刷新后的恢复可能让你意外 —— 如果你昨天打了点破坏性的东西,今天的刷新会重新执行它。最佳实践:那些你不想自动恢复的 pane → 在关标签页前清空内容(Ctrl+A、Del、对空内容点 ▶ = 重置
jzLastRun)。 - 顶层 await 不起作用。把它包进一个 IIFE:
(async () => { await ... })()。 - 访问 MAIN world —— JS pane 在页面上下文里运行(通过
chrome.scripting.executeScriptworld=MAIN),所以它看得到页面的全局变量(React、Redux store、jQuery 等)。和 JS 规则一样。
接下来做什么
JS pane 是 JustZix 4 种「页内窗口」中的第 2 种。我们之前写过 CSS pane(实时 CSS 编辑器)和 JS Console(REPL)。三者合在一起,就是浏览器标签页里一个直接可用的迷你 IDE,按域名划分作用域。
安装 JustZix,在每个页面上获得按需运行的脚本,没有自动运行的风险。
为这篇文章评分
暂无评分 — 成为第一个。