Next.js中阻止router.back()跳转到应用外的外部URL
解决方案:判断router.back()目标是否为外部URL
Next.js的next/router模块没有直接提供方法判断router.back()的跳转目标,我们可以通过以下两种思路实现需求:
方案1:利用浏览器document.referrer
通过对比当前页面的origin和document.referrer的origin,判断前一个页面是否为外部地址。
代码实现
import { useRouter } from 'next/router'; const MyComponent = () => { const router = useRouter(); const handleBack = () => { const currentOrigin = window.location.origin; const referrerUrl = document.referrer; // 处理referrer为空的情况(如直接打开当前页面)或来源为外部域 if (!referrerUrl || new URL(referrerUrl).origin !== currentOrigin) { router.push('/'); } else { router.back(); } }; return <button onClick={handleBack}>返回</button>; }; export default MyComponent;
局限性
仅对页面刷新后的跳转有效,Next.js客户端路由(单页跳转)不会更新document.referrer,无法准确跟踪应用内的导航历史。
方案2:自行维护应用内导航历史
通过监听Next.js路由事件和浏览器popstate事件,手动记录应用内的导航路径,从而判断router.back()是否会跳转到外部。
代码实现
import { useRouter } from 'next/router'; import { useEffect, useState } from 'react'; const MyComponent = () => { const router = useRouter(); // 初始化历史记录为当前路径 const [appHistory, setAppHistory] = useState([router.asPath]); useEffect(() => { // 监听路由完成事件,更新应用内历史记录 const handleRouteChange = (url) => { setAppHistory(prev => { if (prev.at(-1) !== url) { return [...prev, url]; } return prev; }); }; // 监听浏览器前进后退事件,同步更新本地历史 const handlePopState = () => { setAppHistory(prev => prev.length > 1 ? prev.slice(0, -1) : prev); }; router.events.on('routeChangeComplete', handleRouteChange); window.addEventListener('popstate', handlePopState); // 组件卸载时移除监听 return () => { router.events.off('routeChangeComplete', handleRouteChange); window.removeEventListener('popstate', handlePopState); }; }, [router]); const handleBack = () => { // 历史记录长度<=1时,说明back会跳转到外部/空白页,重定向首页 if (appHistory.length <= 1) { router.push('/'); } else { router.back(); } }; return <button onClick={handleBack}>返回</button>; }; export default MyComponent;
优势
- 能准确跟踪所有应用内的客户端导航,不受页面刷新影响。
- 同步浏览器前进后退操作,保证本地历史与实际浏览器历史一致。
内容的提问来源于stack exchange,提问作者rlopxhan21
相关产品推荐
相关产品推荐

