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

Firefox扩展:解决YouTube切换视频时函数仅触发一次的问题

解决YouTube扩展切换视频时无法触发事件的问题

你的问题很典型——YouTube现在是单页应用(SPA),很多路由更新用的是HTML5 History API的pushState/replaceState,而不是传统的hashchange,所以只监听hashchange自然只会触发一次。另外你用的DOM选择器依赖nth-child,也容易因为页面结构微调失效。下面给你两个更可靠的解决方案:

方案1:监听History状态变化(覆盖所有路由更新场景)

YouTube切换视频时,大多会调用history.pushState更新URL路径,而非修改hash。我们可以包装原生的pushState和replaceState方法,触发自定义事件来捕捉这些变化:

// 包装History API方法,触发自定义状态变化事件
(function() {
    const originalPush = history.pushState;
    const originalReplace = history.replaceState;

    history.pushState = function(...args) {
        originalPush.apply(this, args);
        window.dispatchEvent(new Event('routeChange'));
    };

    history.replaceState = function(...args) {
        originalReplace.apply(this, args);
        window.dispatchEvent(new Event('routeChange'));
    };

    // 监听自定义路由变化事件,同时保留hashchange兼容旧场景
    ['routeChange', 'hashchange'].forEach(eventName => {
        window.addEventListener(eventName, () => {
            // 加小延迟确保DOM已更新
            setTimeout(logVideoDetails, 400);
        });
    });
})();

// 封装视频信息获取函数,用更稳定的选择器
function logVideoDetails() {
    const title = document.querySelector('h1.title yt-formatted-string')?.textContent || '标题未加载';
    const likeBtn = document.querySelector('ytd-like-button-renderer#top-level-buttons-computed');
    const dislikeBtn = document.querySelector('ytd-dislike-button-renderer#top-level-buttons-computed');
    
    const likeCount = likeBtn?.getAttribute('aria-label') || '点赞数未加载';
    const dislikeCount = dislikeBtn?.getAttribute('aria-label') || '点踩数未加载';

    console.log(`视频标题: ${title}\n点赞信息: ${likeCount}\n点踩信息: ${dislikeCount}\n`);
}

// 页面初始加载时先执行一次
logVideoDetails();

方案2:用MutationObserver监听视频内容变化(更精准)

如果不想监听路由,直接监听视频核心元素的变化更可靠——切换视频时,标题、点赞按钮这些元素一定会更新。用MutationObserver可以实时捕捉DOM变化:

function logVideoDetails() {
    const title = document.querySelector('h1.title yt-formatted-string')?.textContent || '标题未加载';
    const likeBtn = document.querySelector('ytd-like-button-renderer#top-level-buttons-computed');
    const dislikeBtn = document.querySelector('ytd-dislike-button-renderer#top-level-buttons-computed');
    
    const likeCount = likeBtn?.getAttribute('aria-label') || '点赞数未加载';
    const dislikeCount = dislikeBtn?.getAttribute('aria-label') || '点踩数未加载';

    console.log(`视频标题: ${title}\n点赞信息: ${likeCount}\n点踩信息: ${dislikeCount}\n`);
}

// 初始执行一次
logVideoDetails();

// 监听标题容器的DOM变化
const titleContainer = document.querySelector('#title');
if (titleContainer) {
    const observer = new MutationObserver((mutations) => {
        // 当标题内容或子元素变化时触发
        if (mutations.some(m => m.type === 'childList' || m.type === 'characterData')) {
            setTimeout(logVideoDetails, 300);
        }
    });

    observer.observe(titleContainer, {
        childList: true,
        subtree: true,
        characterData: true
    });
}

关键改进点:

  1. 替换不稳定的选择器:去掉了依赖nth-child的选择器,改用组件ID(比如#top-level-buttons-computed)和明确的标签名,避免页面结构微调导致选择器失效。
  2. 处理DOM加载延迟:用setTimeout给页面一点时间更新DOM,确保能获取到最新的元素信息。
  3. 覆盖所有场景:两种方案分别从路由变化和内容变化入手,都能解决你遇到的“从推荐栏选新视频不触发”的问题,其中MutationObserver方案更精准,因为它直接对应视频内容的更新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:54:41