原生JS实现同一页面重复点击同名锚点时触发输入框聚焦的最简方案
原生JS实现同一页面重复点击同名锚点时触发输入框聚焦的最简方案
嘿,我完全懂你的困扰——重复点同一个锚点时,因为URL的hash没变化,hashchange事件不触发,导致输入框失去焦点后没法自动回去。其实解决起来超简单,不用任何库,只需要给锚点链接加个点击监听就行,我一步步给你说清楚:
问题核心回顾
你的现有代码只监听了hashchange和load事件,但点击同一个锚点时hash不会变,所以聚焦函数不会重新执行。我们需要给每个锚点链接单独加点击监听,不管hash变不变,点击后都强制跑一遍聚焦逻辑。
修改后的完整代码
我保留了你原来的核心逻辑,只新增了必要的监听代码,还加了点鲁棒性判断避免报错:
<!DOCTYPE html> <html> <head> <style> /* 隐藏所有搜索表单默认状态 */ .Startpage, .DuckDuckGo, .Wayback, .Bing, .Google, .YouTube, .Google_Images, .OpenGameArt, .FreeSound, .Amazon { display : none; } /* 锚点激活时显示对应表单 */ #Startpage:target.Startpage, #DuckDuckGo:target.DuckDuckGo, #Wayback:target.Wayback, #Bing:target.Bing, #Google:target.Google, #YouTube:target.YouTube, #Google_Images:target.Google_Images, #OpenGameArt:target.OpenGameArt, #FreeSound:target.FreeSound, #Amazon:target.Amazon { display : block; } </style> </head> <body> <!-- 你的所有搜索表单保持不变 --> <form method="get" action="https://eu.startpage.com/do/search" id="Startpage" class="Startpage"> <input type="text" name="query" value="" placeholder=" Startpage"> </form> <form method="get" action="https://duckduckgo.com/" id="DuckDuckGo" class="DuckDuckGo"> <input type="text" name="q" value="" placeholder=" DuckDuckGo" required="" minlength="1"> </form> <form method="post" action="https://web.archive.org/" id="Wayback" class="Wayback"> <input type="text" name="url" placeholder=" Wayback"> </form> <!-- 省略其他重复表单... --> <h2>Web Search</h2> <ul> <li><a href="#Startpage">Startpage</a></li> <li><a href="#DuckDuckGo">DuckDuckGo</a></li> <li><a href="#Bing">Bing</a></li> <li><a href="#Google">Google</a></li> </ul> <script> function focusOnSearch() { var urlAnchorId = window.location.hash.substring(1); // 新增判断:避免hash为空或目标元素不存在时报错 if (urlAnchorId) { const targetForm = document.getElementById(urlAnchorId); if (targetForm) { const inputField = targetForm.getElementsByTagName("input")[0]; if (inputField) inputField.focus(); } } } // 保留你原来的两个事件监听 window.addEventListener("hashchange", focusOnSearch); window.addEventListener("load", focusOnSearch); // 新增:给所有锚点链接绑定点击监听 function setupAnchorClicks() { // 只选中指向当前页面锚点的a标签(href以#开头) const anchorLinks = document.querySelectorAll('a[href^="#"]'); anchorLinks.forEach(link => { link.addEventListener('click', function() { const targetId = this.href.split('#')[1]; // 确认目标表单存在再执行 if (document.getElementById(targetId)) { // 用setTimeout让浏览器先处理锚点默认行为(比如显示表单),再聚焦 setTimeout(focusOnSearch, 0); } }); }); } // 页面加载完成后初始化锚点监听 window.addEventListener("load", setupAnchorClicks); </script> </body> </html>
关键修改点说明
增强
focusOnSearch的鲁棒性:
加了多层判断,避免页面hash为空、目标表单不存在或找不到输入框时,控制台报红影响其他功能。新增锚点点击监听逻辑:
document.querySelectorAll('a[href^="#"]'):精准选中所有指向当前页面锚点的链接,不会监听外部跳转的链接setTimeout(focusOnSearch, 0):给浏览器留一点时间处理锚点的默认行为(比如通过:targetCSS显示对应表单),再执行聚焦,确保输入框已经显示出来,不会因为元素还隐藏着导致聚焦失败- 绑定在
load事件上:确保所有锚点链接都加载完成后再绑定监听,不会漏绑
为什么这个方案最适合你?
- 完全原生JS,没有任何库依赖,符合你的需求
- 代码逻辑简单,作为新手也能轻松看懂和维护
- 兼顾了「第一次点击锚点」和「重复点击同一锚点」的场景,同时处理了可能的报错情况
试一下这个修改,不管你点多少次同一个锚点,输入框都会自动聚焦啦!要是还有问题随时喊我~ 😊




