Chrome扩展无法获取YouTube播放器及控制栏元素的问题
问题根源分析
- DOMContentLoaded 事件绑定时机错误:你在
newVideoLoaded函数内部绑定该事件时,页面可能早已完成加载,事件不会触发;同时事件回调是异步执行的,函数里的if (youtubeControlBar && youtubePlayer)会在回调执行前就运行,自然拿到的是初始的null值。 - YouTube 是单页应用(SPA):切换视频时不会刷新页面,
DOMContentLoaded仅在首次加载时触发,无法覆盖后续视频加载场景。 - 类名语法错误:
button.className = "ytp-button.question-btn"中的点是CSS选择器分隔符,实际类名需用空格分隔,应写成"ytp-button question-btn"。 - 不必要的资源配置:
web_accessible_resources无需包含contentScript.js,它已通过content_scripts注入页面。
解决方案
1. 修正按钮类名
将按钮类名改为正确格式:
button.className = "ytp-button question-btn";
2. 用 MutationObserver 监听动态元素
YouTube控制栏是动态生成的,使用MutationObserver可在元素出现时立即捕获,同时适配SPA的视频切换场景:
const observeControlBar = () => { const observer = new MutationObserver((mutations) => { const controlBar = document.querySelector(".ytp-left-controls"); const player = document.querySelector(".video-stream"); const existingButton = document.querySelector(".ytp-button.question-btn"); if (controlBar && player && !existingButton) { const button = document.createElement("img"); button.src = chrome.runtime.getURL("assets/youtube.png"); // 修正路径,content脚本相对扩展根目录 button.className = "ytp-button question-btn"; button.title = "Click to Ask Questions"; button.addEventListener("click", addButtonHandler); controlBar.appendChild(button); observer.disconnect(); // 找到元素后停止监听 } }); observer.observe(document.body, { childList: true, subtree: true }); };
3. 监听YouTube页面导航事件
针对SPA的视频切换,监听YouTube自定义事件yt-navigate-finish,每次页面切换(视频加载完成)后重新检查元素:
// 首次加载执行 observeControlBar(); // 监听视频切换事件 document.addEventListener("yt-navigate-finish", () => { observeControlBar(); });
4. 优化 manifest.json 配置
移除web_accessible_resources中的contentScript.js:
"web_accessible_resources": [ { "resources": [ "assets/youtube.png", "youtube.png" ], "matches": ["https://*.youtube.com/*"] } ]
完整修正后的 contentScript.js
const addButtonHandler = () => { // 实现按钮点击逻辑,如暂停/播放视频 const player = document.querySelector(".video-stream"); if (player) { player.paused ? player.play() : player.pause(); } }; const observeControlBar = () => { const observer = new MutationObserver((mutations) => { const controlBar = document.querySelector(".ytp-left-controls"); const player = document.querySelector(".video-stream"); const existingButton = document.querySelector(".ytp-button.question-btn"); if (controlBar && player && !existingButton) { const button = document.createElement("img"); button.src = chrome.runtime.getURL("assets/youtube.png"); button.className = "ytp-button question-btn"; button.title = "Click to Ask Questions"; button.addEventListener("click", addButtonHandler); controlBar.appendChild(button); observer.disconnect(); } }); observer.observe(document.body, { childList: true, subtree: true }); }; // 初始化 observeControlBar(); // 监听YouTube页面切换(视频加载) document.addEventListener("yt-navigate-finish", observeControlBar);
内容的提问来源于stack exchange,提问作者Annoark
相关产品推荐
相关产品推荐

