Next.js 13.5.6(App Router):如何实现链接hover时预取而不是初始渲染?
Next.js 13.5.6 App Router 实现链接悬停预取而非初始视口预取
在你的场景中,Next.js默认会对初始视口内的<Link>自动预取,导致首页加载时产生大量预取请求。要实现鼠标悬停时才预取且保留预取功能,可按以下步骤操作:
步骤1:关闭默认自动预取
给所有<Link>组件添加prefetch={false}属性,禁用Next.js的自动预取逻辑:
<div className="nav"> {nodes.map((node) => { return ( <Link key={node.id} href={`availability/${node.slug}`} prefetch={false} > {node.text} </Link> ) })} </div>
步骤2:手动实现悬停预取
使用Next.js客户端钩子useRouter的prefetch方法,在鼠标悬停链接时触发预取:
'use client'; import { useRouter } from 'next/navigation'; import Link from 'next/link'; export default function NavComponent({ nodes }) { const router = useRouter(); const handleHover = (slug) => { router.prefetch(`availability/${slug}`); }; return ( <div className="nav"> {nodes.map((node) => { return ( <Link key={node.id} href={`availability/${node.slug}`} prefetch={false} onMouseEnter={() => handleHover(node.slug)} > {node.text} </Link> ) })} </div> ); }
可选优化:添加防抖逻辑
为避免快速划过链接时频繁触发预取请求,可给悬停事件添加防抖处理:
'use client'; import { useRouter } from 'next/navigation'; import Link from 'next/link'; import { useEffect, useRef } from 'react'; export default function NavComponent({ nodes }) { const router = useRouter(); const prefetchTimeoutRef = useRef(null); const handleHover = (slug) => { // 清除之前的超时任务 if (prefetchTimeoutRef.current) { clearTimeout(prefetchTimeoutRef.current); } // 延迟150ms后触发预取,仅当用户停留足够久时执行 prefetchTimeoutRef.current = setTimeout(() => { router.prefetch(`availability/${slug}`); }, 150); }; // 组件卸载时清除未执行的超时任务 useEffect(() => { return () => { if (prefetchTimeoutRef.current) { clearTimeout(prefetchTimeoutRef.current); } }; }, []); return ( <div className="nav"> {nodes.map((node) => { return ( <Link key={node.id} href={`availability/${node.slug}`} prefetch={false} onMouseEnter={() => handleHover(node.slug)} > {node.text} </Link> ) })} </div> ); }
关键说明
'use client'指令必须添加,因为useRouter是客户端专属钩子,确保组件在客户端环境运行。prefetch={false}完全禁用自动预取,避免初始加载时的大量请求;手动触发的预取则在用户有点击意向时提前加载页面,保证点击后的响应速度。- 防抖逻辑可根据实际需求调整延迟时间,平衡预取时机和请求频率。
内容的提问来源于stack exchange,提问作者Aniket
相关产品推荐
相关产品推荐

