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

2022年如何在YouTube页面导航时运行Chrome扩展内容脚本?

解决YouTube SPA导航时内容脚本不自动运行的问题

YouTube作为单页应用(SPA),页面导航依赖history.pushState/replaceState而非页面重载,导致内容脚本仅在首次刷新时执行。以下是两种实用解决方案:

方案1:监听History API变化(推荐)

直接捕获YouTube的导航行为,通过重写History方法触发自定义导航事件,在事件回调中执行你的逻辑:

// 保存History原始方法
const originalPushState = history.pushState;
const originalReplaceState = history.replaceState;

// 重写pushState,触发导航事件
history.pushState = function(...args) {
  const result = originalPushState.apply(this, args);
  window.dispatchEvent(new CustomEvent('yt-navigate', { detail: { url: window.location.href } }));
  return result;
};

// 重写replaceState,触发导航事件
history.replaceState = function(...args) {
  const result = originalReplaceState.apply(this, args);
  window.dispatchEvent(new CustomEvent('yt-navigate', { detail: { url: window.location.href } }));
  return result;
};

// 监听浏览器前进/后退的popstate事件
window.addEventListener('popstate', () => {
  window.dispatchEvent(new CustomEvent('yt-navigate', { detail: { url: window.location.href } }));
});

// 核心逻辑:注入元素并执行代码
function handleNavigation() {
  // 清理旧元素,避免重复注入
  const existingElement = document.getElementById('a');
  if (existingElement) existingElement.remove();

  // 等待player元素加载完成
  const checkPlayerInterval = setInterval(() => {
    const player = Array.from(document.querySelectorAll('#player')).pop();
    if (player) {
      clearInterval(checkPlayerInterval);
      player.insertAdjacentHTML("afterend", `<div id="a" style="color:red">Code</div>`);
      // 这里添加你的其他业务代码
    }
  }, 100);
}

// 初始页面加载时执行
window.addEventListener('load', handleNavigation);
// 导航变化时执行
window.addEventListener('yt-navigate', handleNavigation);

方案2:优化现有MutationObserver实现

缩小监听范围,结合URL变化判断,减少不必要的回调触发:

let currentUrl = window.location.href;

function injectScript() {
  const player = Array.from(document.querySelectorAll('#player')).pop();
  if (!player) return;

  const existingElement = document.getElementById('a');
  // URL变化时移除旧元素,避免重复
  if (existingElement) {
    if (window.location.href !== currentUrl) {
      existingElement.remove();
    } else {
      return;
    }
  }

  player.insertAdjacentHTML("afterend", `<div id="a" style="color:red">Code</div>`);
  currentUrl = window.location.href;
  // 这里添加你的其他业务代码
}

// 监听URL变化(同方案1的History重写逻辑)
const originalPushState = history.pushState;
const originalReplaceState = history.replaceState;

history.pushState = function(...args) {
  const result = originalPushState.apply(this, args);
  injectScript();
  return result;
};

history.replaceState = function(...args) {
  const result = originalReplaceState.apply(this, args);
  injectScript();
  return result;
};

window.addEventListener('popstate', injectScript);

// 初始加载+监听核心容器变化
window.addEventListener('load', () => {
  injectScript();
  // 监听YouTube页面的核心容器,缩小监听范围
  const observerTarget = document.querySelector('#page-manager') || document.body;
  const mutationObserver = new MutationObserver((mutations) => {
    // 仅当有新增节点时检查player
    if (mutations.some(m => m.addedNodes.length > 0)) {
      injectScript();
    }
  });
  mutationObserver.observe(observerTarget, {
    childList: true,
    subtree: true
  });
});

关键注意点

  • 避免重复注入:每次导航后先检查并清理旧元素,或通过URL变化判断是否需要重新执行。
  • 元素加载时机:YouTube的player是动态渲染的,需通过定时器或精准监听确保元素存在后再注入。
  • 性能优化:不要监听整个body的子树变化,优先选择#page-manager这类核心容器作为监听目标。

内容的提问来源于stack exchange,提问作者Юра

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 21:55:10