You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

脚本可在浏览器控制台运行但无法在Greasemonkey/Tampermonkey执行求助

问题描述
  • 一段颜色替换代码在浏览器控制台执行完全正常,但在Greasemonkey和Tampermonkey中均无法运行
  • 未收到脚本或工具的任何报错提示
  • 简单alert语句可正常触发,排除脚本加载失败问题
  • 尝试过waitForKeyElements方法,无效果
  • 目标网站:https://*.robertsspaceindustries.com/spectrum/community/SC/forum/*

原脚本代码:

// ==UserScript==
// @name            name
// @description     description
// @version         1
// @author          me
// @match           https://*.robertsspaceindustries.com/spectrum/community/SC/forum/*
// @icon            https://i.imgur.com/km9uoYJ.png
// ==/UserScript==

function hexToRgb(hex) {
  // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
  var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
  hex = hex.replace(shorthandRegex, function(r, g, b) {
    return r + r + g + g + b + b;
  });

  var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
  return result ? "rgb(" + [
    parseInt(result[1], 16),
    parseInt(result[2], 16),
    parseInt(result[3], 16)
  ].join(', ') + ")" : null;
}

// Function to change a color to another one
function colorChange(colorOld, colorNew, strict = false) {
  // If hex notation, convert to rgb
  if (colorOld.includes('#'))
    colorOld = hexToRgb(colorOld);
  // Loop through all elements styles
  [...document.getElementsByTagName('*')].forEach(elm => {
    let cStyle = getComputedStyle(elm);
    [...cStyle].forEach(prop => {
      // Escape if not a string
      if (typeof cStyle[prop] !== 'string') return;
      // Check if colorOld is in property
      if (cStyle[prop].includes(colorOld)){
        // If strict, colorOld is replaced only if it's the only value of the property
        if (!strict || cStyle[prop] === colorOld)
          elm.style[prop] = cStyle[prop].replace(colorOld, colorNew); // Replace color
      }
    })
  })
};

colorChange('#182436', '#ff0000');
问题原因与解决办法

核心原因

  1. 脚本执行时机过早:页面动态加载的元素还未渲染完成,脚本已执行完毕
  2. 颜色格式匹配不兼容:getComputedStyle返回的颜色可能是RGBa格式,或存在空格差异(如rgb(24,36,54) vs rgb(24, 36, 54)),导致匹配失败
  3. 样式优先级被覆盖:脚本设置的行内样式可能被页面自带的高优先级CSS(如!important规则)覆盖

具体修复方案

1. 延迟脚本执行时机

在脚本元信息中添加@run-at document-idle,确保脚本在页面完全加载后执行:

// ==UserScript==
// ... 原有元信息 ...
// @run-at document-idle
// ==/UserScript==

或用DOMContentLoaded事件包裹执行逻辑:

document.addEventListener('DOMContentLoaded', function() {
  colorChange('#182436', '#ff0000');
  console.log('颜色替换已执行');
});

2. 优化颜色匹配逻辑

修改hexToRgb和颜色匹配逻辑,兼容RGBa格式和空格差异:

function hexToRgb(hex, includeAlpha = false) {
  const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
  hex = hex.replace(shorthandRegex, (r, g, b) => r + r + g + g + b + b);

  const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})?$/i.exec(hex);
  if (!result) return null;

  const rgbVals = [
    parseInt(result[1], 16),
    parseInt(result[2], 16),
    parseInt(result[3], 16)
  ];

  if (includeAlpha && result[4]) {
    const alpha = parseInt(result[4], 16) / 255;
    return `rgba(${rgbVals.join(', ')}, ${alpha})`;
  }
  return `rgb(${rgbVals.join(', ')})`;
}

// 统一格式匹配,支持RGB/RGBa、有无空格的情况
function matchesColor(computedColor, targetColor) {
  const cleanComputed = computedColor.replace(/\s+/g, '');
  const cleanTarget = targetColor.replace(/\s+/g, '');
  return cleanComputed === cleanTarget || cleanComputed === `${cleanTarget},1`;
}

function colorChange(colorOld, colorNew, strict = false) {
  let targetColors = [colorOld];
  // 十六进制颜色生成RGB和RGBa两种匹配格式
  if (colorOld.includes('#')) {
    const rgb = hexToRgb(colorOld);
    const rgba = hexToRgb(colorOld, true);
    targetColors = [rgb, rgba];
  }

  [...document.querySelectorAll('*')].forEach(elm => {
    const cStyle = getComputedStyle(elm);
    [...cStyle].forEach(prop => {
      if (typeof cStyle[prop] !== 'string') return;
      targetColors.forEach(target => {
        if (matchesColor(cStyle[prop], target)) {
          if (!strict || matchesColor(cStyle[prop], target)) {
            // 直接设置目标颜色,若被覆盖可添加!important
            // elm.style.setProperty(prop, colorNew, 'important');
            elm.style[prop] = colorNew;
          }
        }
      });
    });
  });
}

3. 监听动态DOM变化

如果页面是单页应用(SPA),内容会动态更新,需用MutationObserver监听DOM变化:

function setupColorObserver() {
  const observer = new MutationObserver(() => {
    colorChange('#182436', '#ff0000');
  });

  observer.observe(document.body, {
    childList: true,
    subtree: true,
    attributes: true,
    attributeFilter: ['style', 'class']
  });
}

document.addEventListener('DOMContentLoaded', setupColorObserver);

4. 调试技巧

在colorChange函数中添加日志,确认是否匹配到目标元素:

if (matchesColor(cStyle[prop], target)) {
  console.log('匹配到元素:', elm, '属性:', prop, '原值:', cStyle[prop]);
  // ... 替换逻辑 ...
}

内容的提问来源于stack exchange,提问作者Forceflow

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 22:27:20