油猴脚本开发全指南:从入门到功能扩展

一、油猴脚本开发基础

油猴脚本(Tampermonkey/Violentmonkey)是浏览器扩展中的用户脚本管理器,允许开发者通过JavaScript动态修改网页行为。其核心优势在于无需修改服务器代码即可实现个性化功能定制,适用于前端调试、广告拦截、数据采集等场景。

1.1 开发环境搭建

  1. 安装管理器:主流浏览器扩展商店搜索”用户脚本管理器”安装(如Tampermonkey)
  2. 创建新脚本:点击扩展图标→管理面板→添加新脚本
  3. 编辑器配置:建议启用语法高亮、自动补全等开发者工具

1.2 脚本元信息规范

每个脚本必须包含标准化的元信息块,用于声明脚本属性和权限:

  1. // ==UserScript==
  2. // @name 页面元素定制器
  3. // @namespace https://example.com/scripts
  4. // @version 1.0.1
  5. // @description 修改搜索按钮样式和交互逻辑
  6. // @author Developer
  7. // @match https://*.example.com/*
  8. // @grant GM_addStyle
  9. // @require https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js
  10. // ==/UserScript==

关键字段说明:

  • @match:精确控制脚本生效的URL模式,支持通配符
  • @grant:声明需要的特殊API权限(如GM_xmlhttpRequest)
  • @require:引入外部依赖库(需支持CORS)

二、核心开发技术解析

2.1 DOM操作实战

以修改搜索按钮为例,展示元素选择与样式调整:

  1. (function() {
  2. 'use strict';
  3. // 元素选择与修改
  4. const searchBtn = document.querySelector('.search-btn');
  5. if (searchBtn) {
  6. // 修改文本内容
  7. searchBtn.value = '立即搜索';
  8. // 动态样式注入
  9. GM_addStyle(`
  10. .search-btn {
  11. background: linear-gradient(135deg, #ff9a9e 0%, #fad0c4 100%);
  12. border-radius: 25px;
  13. transition: all 0.3s ease;
  14. }
  15. .search-btn:hover {
  16. transform: scale(1.05);
  17. box-shadow: 0 5px 15px rgba(0,0,0,0.1);
  18. }
  19. `);
  20. }
  21. })();

技术要点:

  1. 使用querySelector进行精准元素定位
  2. 通过GM_addStyle实现跨域样式注入(需声明@grant GM_addStyle
  3. CSS过渡效果增强用户体验

2.2 事件监听与交互增强

实现按钮点击后的二次确认:

  1. searchBtn.addEventListener('click', function(e) {
  2. if (!confirm('确定要执行搜索吗?')) {
  3. e.preventDefault();
  4. e.stopPropagation();
  5. this.classList.add('shake-animation');
  6. setTimeout(() => this.classList.remove('shake-animation'), 500);
  7. }
  8. });
  9. // 添加动画样式
  10. GM_addStyle(`
  11. @keyframes shake {
  12. 0%, 100% { transform: translateX(0); }
  13. 20%, 60% { transform: translateX(-5px); }
  14. 40%, 80% { transform: translateX(5px); }
  15. }
  16. .shake-animation {
  17. animation: shake 0.5s;
  18. }
  19. `);

2.3 数据持久化方案

利用GM_setValue/GM_getValue实现配置存储:

  1. // 保存用户偏好
  2. function savePreference(key, value) {
  3. GM_setValue(key, JSON.stringify(value));
  4. }
  5. // 读取配置
  6. function getPreference(key, defaultValue) {
  7. const val = GM_getValue(key);
  8. return val ? JSON.parse(val) : defaultValue;
  9. }
  10. // 使用示例
  11. const theme = getPreference('uiTheme', 'light');
  12. document.body.className = theme;

三、高级功能开发

3.1 跨域请求处理

通过GM_xmlhttpRequest实现安全的数据获取:

  1. function fetchData(url, callback) {
  2. GM_xmlhttpRequest({
  3. method: "GET",
  4. url: url,
  5. onload: function(response) {
  6. if (response.status === 200) {
  7. callback(null, JSON.parse(response.responseText));
  8. } else {
  9. callback(new Error(`Request failed: ${response.status}`));
  10. }
  11. },
  12. onerror: function(error) {
  13. callback(error);
  14. }
  15. });
  16. }

3.2 模块化开发实践

采用IIFE模式组织代码:

  1. const SearchEnhancer = (function() {
  2. const PRIVATE_VAR = 'private data';
  3. function init() {
  4. _setupUI();
  5. _bindEvents();
  6. }
  7. function _setupUI() {
  8. // 私有方法实现
  9. }
  10. return {
  11. init: init,
  12. updateConfig: function(config) {
  13. // 公共API
  14. }
  15. };
  16. })();
  17. // 初始化
  18. SearchEnhancer.init();

3.3 调试与错误处理

  1. 日志系统:使用console.log配合@grant GM_log
  2. 错误捕获
    1. try {
    2. // 危险操作
    3. } catch (e) {
    4. console.error('Script error:', e);
    5. GM_notification({
    6. title: '脚本错误',
    7. text: e.message,
    8. timeout: 5000
    9. });
    10. }

四、最佳实践与安全规范

4.1 性能优化建议

  1. 使用MutationObserver监听DOM变化替代轮询
  2. 对高频事件进行节流处理:
    1. function throttle(func, limit) {
    2. let lastFunc;
    3. let lastRan;
    4. return function() {
    5. const context = this;
    6. const args = arguments;
    7. if (!lastRan) {
    8. func.apply(context, args);
    9. lastRan = Date.now();
    10. } else {
    11. clearTimeout(lastFunc);
    12. lastFunc = setTimeout(function() {
    13. if ((Date.now() - lastRan) >= limit) {
    14. func.apply(context, args);
    15. lastRan = Date.now();
    16. }
    17. }, limit - (Date.now() - lastRan));
    18. }
    19. };
    20. }

4.2 安全注意事项

  1. 避免直接执行用户输入的内容
  2. @match规则进行最小化授权
  3. 敏感操作前进行权限确认

4.3 版本管理策略

  1. 遵循语义化版本规范(Major.Minor.Patch)
  2. 维护CHANGELOG.md记录变更
  3. 使用@updateURL实现自动更新

五、完整案例演示

以下是一个完整的搜索页面增强脚本:

  1. // ==UserScript==
  2. // @name 智能搜索增强
  3. // @namespace https://example.com
  4. // @version 1.2.0
  5. // @description 提供搜索按钮美化、历史记录和快捷输入功能
  6. // @match https://*.example.com/search*
  7. // @grant GM_addStyle
  8. // @grant GM_setValue
  9. // @grant GM_getValue
  10. // @grant GM_registerMenuCommand
  11. // @grant GM_notification
  12. // ==/UserScript==
  13. (function() {
  14. 'use strict';
  15. // 配置初始化
  16. const CONFIG = {
  17. theme: getPreference('theme', 'dark'),
  18. historyLimit: getPreference('historyLimit', 5)
  19. };
  20. // UI增强
  21. function enhanceUI() {
  22. GM_addStyle(`
  23. body { font-family: 'Segoe UI', sans-serif; }
  24. .search-container {
  25. max-width: 800px;
  26. margin: 2rem auto;
  27. padding: 2rem;
  28. border-radius: 10px;
  29. box-shadow: 0 10px 30px rgba(0,0,0,0.1);
  30. }
  31. .search-btn {
  32. /* 样式定义 */
  33. }
  34. `);
  35. document.body.classList.add(CONFIG.theme);
  36. }
  37. // 历史记录管理
  38. class SearchHistory {
  39. constructor(limit = 5) {
  40. this.limit = limit;
  41. this.items = this._load();
  42. }
  43. _load() {
  44. const data = GM_getValue('searchHistory', '[]');
  45. return JSON.parse(data).slice(-this.limit);
  46. }
  47. add(query) {
  48. this.items.push(query);
  49. this.items = [...new Set(this.items)].slice(-this.limit);
  50. GM_setValue('searchHistory', JSON.stringify(this.items));
  51. }
  52. getSuggestions() {
  53. return this.items;
  54. }
  55. }
  56. // 初始化
  57. function init() {
  58. enhanceUI();
  59. const history = new SearchHistory(CONFIG.historyLimit);
  60. // 快捷菜单
  61. GM_registerMenuCommand('清除历史记录', () => {
  62. history = new SearchHistory();
  63. GM_notification({title: '操作成功', text: '历史记录已清除'});
  64. });
  65. // 表单处理
  66. const form = document.querySelector('#searchForm');
  67. if (form) {
  68. form.addEventListener('submit', (e) => {
  69. const input = form.querySelector('input[name="q"]');
  70. if (input.value.trim()) {
  71. history.add(input.value.trim());
  72. }
  73. });
  74. }
  75. }
  76. // 启动
  77. init();
  78. })();

通过系统学习本文内容,开发者可以掌握从基础DOM操作到高级模块化开发的全流程技术,构建出安全、高效、可维护的用户脚本解决方案。建议结合具体项目需求,逐步实践各技术模块,最终实现完整的网页交互增强功能。