油猴脚本注入YouTube无效,控制台运行正常问题求助
问题原因
YouTube 是单页应用(SPA),你的脚本在页面初始加载完成后就立即执行,但此时#actions元素还未被渲染(只有进入具体视频页面后,该元素才会动态生成)。直接调用document.getElementById('actions')会返回null,导致后续代码无法执行——这就是脚本在油猴插件里无效,但控制台手动运行有效的原因(控制台运行时页面已经完成视频区域的渲染,元素存在)。
解决方案
可以通过监听DOM变化的方式,在#actions元素出现时再执行添加按钮的逻辑,推荐两种实现方式:
方案1:使用MutationObserver(兼容所有油猴插件)
这种方式通过监听DOM树变化,高效捕获目标元素的生成时机,适配所有油猴类插件:
// ==UserScript== // @name Youtube Downloader // @namespace http://tampermonkey.net/ // @version 0.2 // @description Download Youtube Videos With One Click! // @author qweren // @match https://www.youtube.com/* // @icon https://upload.wikimedia.org/wikipedia/commons/thumb/0/09/YouTube_full-color_icon_%282017%29.svg/1024px-YouTube_full-color_icon_%282017%29.svg.png // ==/UserScript== (function() { 'use strict'; // 定义添加按钮的核心逻辑 function addDownloadButton() { const actionsDiv = document.getElementById('actions'); // 避免重复添加按钮 if (!actionsDiv || document.querySelector('#yt-download-btn')) return; const newButton = document.createElement('button'); newButton.id = 'yt-download-btn'; newButton.textContent = '下载视频'; // 适配YouTube原生按钮样式 newButton.style.padding = '0 16px'; newButton.style.height = '36px'; newButton.style.border = 'none'; newButton.style.borderRadius = '18px'; newButton.style.backgroundColor = '#ff0000'; newButton.style.color = 'white'; newButton.style.cursor = 'pointer'; newButton.style.marginLeft = '8px'; newButton.addEventListener('click', function() { alert('下载功能待实现!'); }); actionsDiv.appendChild(newButton); console.log('下载按钮已添加'); } // 初始检查一次(针对直接打开视频页的场景) addDownloadButton(); // 监听DOM变化,捕获#actions元素的生成 const observer = new MutationObserver((mutations) => { mutations.forEach(() => { if (document.getElementById('actions')) { addDownloadButton(); } }); }); // 监听整个页面的DOM节点变化 observer.observe(document.body, { childList: true, subtree: true }); })();
方案2:使用Tampermonkey内置的waitForKeyElements(更简洁)
Tampermonkey提供了waitForKeyElements工具函数,可自动等待目标元素出现后执行回调,代码更简洁:
// ==UserScript== // @name Youtube Downloader // @namespace http://tampermonkey.net/ // @version 0.2 // @description Download Youtube Videos With One Click! // @author qweren // @match https://www.youtube.com/* // @icon https://upload.wikimedia.org/wikipedia/commons/thumb/0/09/YouTube_full-color_icon_%282017%29.svg/1024px-YouTube_full-color_icon_%282017%29.svg.png // @require https://greasyfork.org/scripts/3988-waitforkeyelements/code/waitForKeyElements.js?version=115012 // ==/UserScript== (function() { 'use strict'; waitForKeyElements('#actions', function(actionsDiv) { // 避免重复添加 if (document.querySelector('#yt-download-btn')) return; const newButton = document.createElement('button'); newButton.id = 'yt-download-btn'; newButton.textContent = '下载视频'; // 适配YouTube原生按钮样式 newButton.style.padding = '0 16px'; newButton.style.height = '36px'; newButton.style.border = 'none'; newButton.style.borderRadius = '18px'; newButton.style.backgroundColor = '#ff0000'; newButton.style.color = 'white'; newButton.style.cursor = 'pointer'; newButton.style.marginLeft = '8px'; newButton.addEventListener('click', function() { alert('下载功能待实现!'); }); actionsDiv.appendChild(newButton); console.log('下载按钮已添加'); }); })();
关键优化点
- 加入重复添加检查,防止页面切换或DOM重渲染时多次生成按钮
- 给按钮添加了适配YouTube的基础样式,保证视觉一致性
- 两种方案分别适配不同插件场景,可根据使用的油猴工具选择
内容的提问来源于stack exchange,提问作者Eren
相关产品推荐
相关产品推荐

