JavaScript如何正确选中并聚焦YouTube首页搜索输入框
出错原因
- 选择元素的API用错:你选YouTube搜索框时调用的是
document.querySelectorAll,这个接口返回的是DOM节点集合,不是单个元素,直接对集合调用focus()、设置selectionStart属性会直接抛出JS错误,后续逻辑全部中断。 - 选择器优先级逻辑错误:YouTube页面加载初期,DOM里会存在其他匹配
form input:not([type=hidden])规则的隐藏/预加载输入项,代码会直接命中这个分支,根本走不到你写的YouTube搜索框匹配逻辑。 - 选择器本身容错性差:你写的
#search.ytd-searchbox要求元素同时携带ytd-searchbox类名,但YouTube是单页应用,类名是组件渲染完成后才会注入的,代码执行过早时就算id匹配,也会因为类名没加载完匹配失败。 - 缺少动态渲染适配:YouTube的组件是渐进式渲染的,代码执行时如果搜索框还没完成挂载,就算选择器写对了也拿不到元素,且页面初始加载时自带焦点拦截逻辑,会把默认焦点从搜索框移走。
修正方案
调整选择器优先级,优先匹配id为search的搜索框,再兜底通用输入框规则;加重试逻辑适配动态渲染场景;修正API调用错误,补充元素可见性校验,避开隐藏的无效元素。
修正后的可直接运行代码如下:
function pSetFocus() { let targetInput = null; // 按优先级排列选择器,高优先级的专属站点规则放前面 const prioritySelectors = [ "#search", // YouTube 搜索框唯一id,优先级最高 "*[autofocus]", "form input:not([type=hidden]):not([disabled])" ]; // 遍历选择器,找到第一个可见的可交互输入框 for (const selector of prioritySelectors) { const el = document.querySelector(selector); // offsetParent不为null代表元素不是隐藏状态 if (el && el.offsetParent !== null) { targetInput = el; break; } } // 没找到元素就间隔100ms重试,最多重试10次,适配单页应用动态渲染 if (!targetInput) { window._focusRetryTimes = window._focusRetryTimes || 0; if (window._focusRetryTimes < 10) { window._focusRetryTimes += 1; setTimeout(pSetFocus, 100); } return; } window._focusRetryTimes = 0; // 执行聚焦和光标定位 targetInput.focus(); targetInput.selectionStart = targetInput.selectionEnd = targetInput.value.length; // 滚动时预留80px偏移,避开YouTube固定顶部导航栏遮挡 const scrollTop = targetInput.getBoundingClientRect().top + window.scrollY - 80; window.scrollTo({ top: scrollTop, behavior: "smooth" }); } // 页面完全加载后执行,也可以根据需求手动触发 if (document.readyState === "complete") { pSetFocus(); } else { window.addEventListener("load", pSetFocus, { once: true }); }
如果你是在油猴脚本、浏览器扩展内容脚本中运行这段代码,把脚本注入时机设置为「页面加载完成后」即可,当前YouTube的搜索输入框在主文档流内,不需要额外穿透Shadow DOM就能正常选中。
内容的提问来源于stack exchange,提问作者tmighty
相关产品推荐
相关产品推荐

