
本文详解如何使用 next/link 在 Next.js 中实现跨页面传参并打开新标签页,涵盖 URL 查询参数传递、接收端解析、注意事项及最佳实践。
本文详解如何使用 `next/link` 在 next.js 中实现跨页面传参并打开新标签页,涵盖 url 查询参数传递、接收端解析、注意事项及最佳实践。
在 Next.js 中,组件间无法像 Flutter 的 MaterialPageRoute(builder: (context) => Page({...})) 那样直接以 props 形式实例化目标页面——因为服务端渲染(SSR)和静态生成(SSG)场景下,页面是独立路由单元,不具备“构造时传参”的运行时上下文。但可通过 URL 查询参数(query string) 安全、标准且兼容性极佳地实现等效效果:点击链接后在新标签页打开目标页,并携带结构化数据。
✅ 正确做法:用 next/link + router.query 实现参数传递
发送端(源页面):构造带查询参数的链接
import Link from 'next/link';
const SenderPage = () => {
const exampleTitle = '欢迎来到仪表盘';
const exampleDesc = '这是由上一页动态传入的描述信息';
return (
<Link
href={{
pathname: '/page', // ✅ 替换为你的实际页面路径(如 '/dashboard')
query: {
title: exampleTitle,
desc: exampleDesc
}
}}
passHref
>
<a
target="_blank"
rel="noopener noreferrer"
className="text-blue-600 hover:underline"
>
在新标签页打开页面
</a>
</Link>
);
};
export default SenderPage;? 关键点说明:
- href 接收对象形式,pathname 指定路由路径,query 自动序列化为 URL 查询字符串(如 /page?title=...&desc=...);
- passHref 是必需的——它确保 <a> 标签获得正确的 href 属性,保障可访问性、SEO 和浏览器原生行为(如右键“在新标签页中打开”);
- target="_blank" 和 rel="noopener noreferrer" 是安全必备:防止新开页面通过 window.opener 访问源页面,规避潜在安全风险(如钓鱼或跳转劫持)。
接收端(目标页面):从路由中解构参数
import { useRouter } from 'next/router';
import { useEffect, useState } from 'react';
const Page = () => {
const router = useRouter();
const { title, desc } = router.query;
// ⚠️ 注意:router.query 初始为 {},SSR/SSG 时可能为空,需做类型守卫或加载态处理
const [pageData, setPageData] = useState<{ title: string; desc: string } | null>(null);
useEffect(() => {
if (title && desc) {
setPageData({
title: Array.isArray(title) ? title[0] : title,
desc: Array.isArray(desc) ? desc[0] : desc,
});
}
}, [title, desc]);
if (!pageData) {
return <div className="p-4">加载中...</div>;
}
return (
<div className="p-6 max-w-2xl mx-auto">
<h1 className="text-2xl font-bold text-gray-800">{pageData.title}</h1>
<p className="mt-2 text-gray-600">{pageData.desc}</p>
<button
onClick={() => window.history.back()}
className="mt-4 px-4 py-2 bg-gray-100 rounded hover:bg-gray-200"
>
返回上一页
</button>
</div>
);
};
export default Page;? 提示:
- router.query 中的值始终为字符串或字符串数组(当同名参数多次出现时),即使你传入数字或布尔值也会被序列化为字符串,务必手动转换(如 Number(router.query.id));
- 若需传递复杂对象(如嵌套结构),应先 JSON.stringify() 后 encodeURIComponent() 编码,接收端再反向解码(但建议优先考虑服务端 API 或状态管理,避免 URL 过长或不安全);
- 使用 useEffect 响应 router.query 变化,是处理客户端路由更新的标准方式(尤其在 App Router 中推荐用 useSearchParams,但本例基于 Pages Router)。
❌ 常见误区澄清
不要混用 next/navigation 与 next/link?
完全可以——二者定位不同:next/navigation(App Router)提供 useRouter, redirect, notFound 等服务端/客户端导航能力;next/link(Pages Router 或 App Router 均支持)是声明式预取链接组件。在 Pages Router 项目中,next/link 是官方推荐的链接方案;在 App Router 中,也可继续使用 Link 组件(来自 next/link),它已适配新架构。能否用 window.open() + useState 传参?
❌ 不可行。新开窗口无法直接访问父窗口的 React 状态(跨域/同域均受同源策略与执行上下文隔离限制),URL 参数是唯一可靠、通用、可书签化的方案。是否必须用 Link?纯 <a> 行不行?
纯 <a> 可工作,但会丢失 prefetch(预加载)、shallow routing 等优化能力,且在动态路由中难以正确处理 basePath、locale 等配置。Link 是 Next.js 的最佳实践封装。
✅ 总结:关键原则
| 场景 | 推荐方式 | 原因 |
|---|---|---|
| 传简单字符串/数字 | query 对象 + router.query 解析 | 标准、轻量、可缓存、可分享 |
| 传敏感数据(如 token、ID) | ❌ 避免 URL 传输,改用服务端 session 或 API 请求 | 防止日志泄露、历史记录残留、代理嗅探 |
| 需要强类型校验 | 结合 zod 解析 router.query,抛出错误或重定向 | 提升健壮性,避免运行时崩溃 |
| App Router 用户 | 使用 useSearchParams() 替代 useRouter().query,更语义化 | searchParams.get('title') 更直观,自动处理编码 |
只要遵循 URL 参数传递这一 Web 基础范式,你就能在 Next.js 中优雅复现 Flutter 式的页面跳转与参数注入体验——简洁、可靠,且完全契合现代前端工程规范。










