Web Dev

next.js Router和userRouter的区别

2024年7月17日 (1年前)

在 Next.js 中,RouteruseRouter 都是用于路由管理的核心 API,但它们的适用场景和使用方式有重要区别:


1. Router (Next.js 的路由对象)

特点:

  • 低级别路由对象:直接从 next/router 导入的原始路由类
  • 需要手动订阅更新:不会自动触发组件重渲染
  • 适用于非组件环境:如 utility 文件、API 路由等

典型用法:

import { Router } from "next/router";

// 编程式导航(在非组件环境中)
Router.push("/dashboard");

// 监听路由事件
Router.events.on("routeChangeStart", (url) => {
  console.log("路由开始变化:", url);
});

常用方法/事件:

  • Router.push() 编程式导航
  • Router.replace() 替换当前路由(不保留历史记录)
  • Router.events.on() 监听路由事件

2. useRouter (React Hook)

特点:

  • 组件级 Hook:只能在 React 组件或自定义 Hook 中使用
  • 自动订阅更新:路由变化时会触发组件重渲染
  • 访问当前路由状态:可直接获取 query、pathname 等实时信息

典型用法:

import { useRouter } from "next/router";

function Component() {
  const router = useRouter();

  // 获取当前路由信息
  console.log(router.pathname); // 当前路径
  console.log(router.query); // 查询参数

  // 编程式导航
  const handleClick = () => {
    router.push("/profile?id=123");
  };

  return <button onClick={handleClick}>跳转</button>;
}

常用属性/方法:

  • router.query 获取动态路由参数和查询字符串
  • router.pathname 当前路由路径(不包含查询参数)
  • router.push() 组件内的编程式导航
  • router.asPath 包含查询参数的实际 URL

何时选择?

  1. useRouter 如果:

    • 在 React 组件中需要响应式路由数据
    • 需要访问当前路由参数(如动态路由 [id].js
    • 要实现基于路由的 UI 逻辑(如高亮导航菜单)
  2. Router 如果:

    • 在非组件文件中操作导航(如 utils/auth.js
    • 需要全局监听路由事件(如页面加载进度条)
    • _app.js 中设置全局路由处理器

组合使用示例

// utils/navigation.js
import { Router } from "next/router";

export const logout = () => {
  Router.push("/login"); // 在工具文件中使用
};

// components/Profile.js
import { useRouter } from "next/router";

export default function Profile() {
  const router = useRouter();

  // 响应式获取URL参数
  const { userId } = router.query;

  return <div>User ID: {userId}</div>;
}

注意事项

  1. useRouter 必须在组件顶层调用(遵守 Hook 规则)
  2. Router.events 的监听器需要手动移除(防止内存泄漏)
    useEffect(() => {
      const handler = (url) => console.log(url);
      Router.events.on("routeChangeStart", handler);
      return () => Router.events.off("routeChangeStart", handler);
    }, []);
  3. 在 Next.js 13+ 的 App Router 中,推荐使用新的 usePathnameuseSearchParams 替代部分功能