如何在 Greasemonkey 中重定向到我的 YouTube 订阅页面?

How can I redirect to my youtube subscription page in Greasemonkey?

我不想在我的开始屏幕上看到令人分心的 YouTube 推荐,我只想在我转到 YouTube 的 / 路径时被重定向到我的订阅页面。 我试图通过使用 javascript 自动从 / 路径重定向到 /feed/subscriptions 路径来重新设计 DOM 中的 YouTube 页面。

我创建了以下脚本,不幸的是它只适用于页面重新加载。

// ==UserScript==
// @name        YT redir /home -> /sub
// @match       https://www.youtube.com/*
// @grant       none
// @run-at      document-start
// @version     1.0
// @author      -
// @description 5/30/2020, 12:16:13 PM
// ==/UserScript==

var current_location = location.pathname;
if(current_location == "/"){
     window.location.replace("https://youtube.com/feed/subscriptions")
}

我希望这个脚本在我浏览 youtube 并单击主页或 youtube 徽标按钮时也能正常工作。但是,它仅适用于页面重新加载。

如何在不重新加载 youtube 的情况下使这个脚本工作?

为了解决这个问题以实现相同的目标,我尝试只替换主页按钮和徽标按钮的 href 属性。

// ==UserScript==
// @name        YT test
// @match       https://www.youtube.com/*
// @grant       none
// @run-at      document-start
// @version     1.0
// @author      -
// @description 5/30/2020, 12:16:13 PM
// ==/UserScript==

document.getElementById("endpoint").href="/feed/subscriptions";
document.getElementById("endpoint").removeAttribute('class');
document.getElementById("logo").href="/feed/subscriptions";
document.getElementById("logo").removeAttribute('class');

然而,尽管这些命令在JS控制台中有效,但即使我将run-at属性设置为document-end,它们也不会像greasemonkey脚本那样生效。

如何通过 Greasemonkey 自动进行这些更改?

问题:

  1. YouTube页面在一个文档中有多个相同id的元素,违反了HTML标准,所以document.getElementById("logo")会找错一。您可以改用 document.querySelector('a#logo')

  2. 页面是使用 JavaScript 动态构建的,因此元素可能会在 DOMContentLoaded 事件发生后长时间出现。您可以使用 MutationObserver(可能会消耗资源)或 setTimeout/setInterval(不精确)。

  3. YouTube 网站是一个 SPA(单页应用程序),它通过使用 History API 模仿导航,但用户脚本仅在真正的导航上执行。


解决方案:

可以有很多解决方案,可以说,但我建议在捕获阶段使用一个简单的 click 监听器(addEventListener 的第三个参数是 true),这样你就不必依赖在元素的确切选择器上,当站点代码将来更新时,它可能会发生不可预测的变化。

// ==UserScript==
// @name        YT redir /home -> /sub
// @match       https://www.youtube.com/*
// @grant       none
// @run-at      document-start
// ==/UserScript==

if (location.pathname === '/') {
  location.pathname = '/feed/subscriptions';
}
window.addEventListener('click', e => {
  const a = e.target.closest('a');
  if (a && a.href === 'https://www.youtube.com/') {
    a.pathname = '/feed/subscriptions';
    a.className = '';
  }
}, true);