Violentmonkey 速查表
版本unknown 更新日志2026-01-30 GitHubviolentmonkey/violentmonkey
400px

元数据块 (Metadata Block) #

脚本头部配置,定义基本信息、权限和运行规则。

// ==UserScript==
// @name            Script Name
// @namespace       https://example.com
// @version         1.0.0
// @description     Description
// @author          Author
// @match           *://google.com/*
// @grant           GM_setValue
// @grant           GM_xmlhttpRequest
// @require         https://cdn.js/jquery.min.js
// @run-at          document-end
// @connect         api.example.com
// ==/UserScript==
@name脚本名称
@namespace唯一标识符
@match匹配规则 (推荐)
@grant申请权限
@require引入JS库
@run-at执行时机
@connect允许跨域域名

执行时机 (@run-at)

document-start文档开始加载
document-body<body>出现时
document-endDOM完成 (默认)
document-idle页面完全加载

匹配规则

// @match *://*/*           // 所有 http/https
// @match https://google.com/*
// @include /https:\/\/.*\.com\/.*/  // 正则
// @exclude https://*/login

数据存储 (Storage) #

@grant GM_setValue 等。

// 存储(支持任意类型)
GM_setValue('config', { theme: 'dark' });

// 读取(支持默认值)
const conf = GM_getValue('config', {});

// 删除
GM_deleteValue('config');

// 列出所有键
const keys = GM_listValues();

// 监听变化(跨标签页)
GM_addValueChangeListener('key', (n, o, v, r) => {
  console.log('Changed:', v);
});

网络请求 (XHR) #

跨域请求需 @grant GM_xmlhttpRequest@connect

GM_xmlhttpRequest({
  method: 'GET',
  url: 'https://api.example.com/data',
  headers: {
    'Authorization': 'Bearer token'
  },
  onload: (res) => {
    if (res.status === 200) {
      console.log(res.responseText);
    }
  },
  onerror: (err) => console.error(err),
  ontimeout: () => console.error('超时')
});

样式与资源 #

注入 CSS

GM_addStyle(`
  #my-panel {
    position: fixed;
    top: 10px; right: 10px;
    z-index: 99999;
  }
`);

使用外部资源

// @resource myCSS https://site.com/s.css
const css = GM_getResourceText('myCSS');
GM_addStyle(css);

// @resource icon https://site.com/icon.png
const iconUrl = GM_getResourceURL('icon');
// 返回 base64 数据 URL

界面交互 (UI) #

菜单命令

GM_registerMenuCommand('⚙️ 设置', () => {
  toggleSettings();
}, 's'); // 快捷键

通知与剪贴板

// 桌面通知
GM_notification({
  text: '任务完成',
  title: '提示',
  onclick: () => console.log('点击')
});

// 写入剪贴板
GM_setClipboard('文本内容');

// 新标签页打开
GM_openInTab(url, { active: false });

DOM 观察 #

SPA 必备,监听动态加载元素。

const obs = new MutationObserver(muts => {
  for (const m of muts) {
    for (const node of m.addedNodes) {
      if (node.nodeType === 1 &&
          node.matches('.ad-banner')) {
        node.remove();
      }
    }
  }
});

obs.observe(document.body, {
  childList: true,
  subtree: true
});

实用片段 (Snippets)

等待元素

function waitFor(selector, timeout = 10000) {
  return new Promise((resolve, reject) => {
    if (document.querySelector(selector)) {
      return resolve(document.querySelector(selector));
    }
    const observer = new MutationObserver(() => {
      const el = document.querySelector(selector);
      if (el) {
        observer.disconnect();
        resolve(el);
      }
    });
    observer.observe(document.body, {
      childList: true, subtree: true
    });
    setTimeout(() => {
      observer.disconnect();
      reject(new Error('Timeout'));
    }, timeout);
  });
}

// await waitFor('.btn');

防抖与节流

防抖 (debounce)

function debounce(fn, delay = 300) {
  let timer = null;
  return function(...args) {
    clearTimeout(timer);
    timer = setTimeout(() => fn.apply(this, args), delay);
  };
}

节流 (throttle)

function throttle(fn, interval = 300) {
  let lastTime = 0;
  return function(...args) {
    const now = Date.now();
    if (now - lastTime >= interval) {
      lastTime = now;
      fn.apply(this, args);
    }
  };
}

现代 API (GM.*) #

Greasemonkey 4+ 风格的异步 API。

(async () => {
  // 数据存储
  await GM.setValue('key', 123);
  const val = await GM.getValue('key');
  await GM.deleteValue('key');
  const keys = await GM.listValues();
  
  // 网络请求(回调方式不变)
  GM.xmlHttpRequest({
    url: '...',
    onload: res => console.log(res)
  });
})();
GM.setValue异步存储
GM.getValue异步读取
GM.xmlHttpRequest网络请求

调试技巧

unsafeWindow

// 访问页面原生 window
unsafeWindow.nativeFunction();

// 暴露调试变量
unsafeWindow.myDebug = { config, data };

错误捕获

// 全局错误
window.addEventListener('error', (e) => {
  console.error('[Script]', e.error);
});

// Promise 错误
window.addEventListener('unhandledrejection', (e) => {
  console.error('[Script]', e.reason);
});

完整示例

自动暗黑模式脚本

// ==UserScript==
// @name         暗黑模式
// @match        https://example.com/*
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_registerMenuCommand
// @grant        GM_addStyle
// ==/UserScript==

(function() {
  const KEY = 'darkEnabled';
  let enabled = GM_getValue(KEY, true);
  
  function apply() {
    if (enabled) {
      GM_addStyle(`body {
        background: #1a1a1a !important;
        color: #e0e0e0 !important;
      }`);
    }
  }
  
  GM_registerMenuCommand('🌙 切换', () => {
    enabled = !enabled;
    GM_setValue(KEY, enabled);
    location.reload();
  });
  
  apply();
})();