关于Next.js的App Router:详细笔记

简介

  • Next.js App Router 是基于 React 的路由系统,提供了新的功能和概念,目前已接近完全稳定。

  • 本文将介绍 App Router 的基础功能,包括路由、布局、数据获取、元数据等。

1. 路由系统

布局(Layouts)

  • 文件位置:在 app 文件夹中,创建 layout.tsx。

图片

  • 作用:定义整个应用的路由布局,接收子组件(children),并渲染它们。

图片

  • 特点:

    • 页面与布局是通过组合 React 组件实现的。

    • 当访问 localhost:3000 时,页面的渲染是布局和页面的组合。

图片

图片

页面组件(Pages)

  • 文件位置:创建 page.tsx 文件。

  • 作用:

    • 定义页面内容(每个 page.tsx 是一个路由)。

图片

    • 页面与布局组合,生成可访问的 UI。

  • 默认行为:App Router 中的所有页面和布局组件默认是 React 服务器组件(Server Components)。

    • 服务器组件只在服务器端运行,减少了客户端的 JavaScript 代码量,提高了安全性。

    • 如果这个页面中有客户端(运行在前端)组件,需要在page.tsx的第一行加上'use client'

    • 常见的客户端组件:React状态-useState,useReducer,useEffect...

图片

动态路由

  • 使用方括号([id])定义动态路由。例如:

    • 新建文件夹 blog,在其内部创建 [id] 文件夹。

    • 在 [id] 文件夹中定义 page.tsx,路由格式为 /blog/:id。

  • 在组件中通过 props.params.id 获取动态路由段的值。

图片

2. 数据获取(Data Fetching)

基本数据获取

  • App Router 简化了数据获取,基于 React 的新特性构建。

  • 异步组件:将组件声明为异步(async),可通过 await 获取动态数据。

  • const response = await fetch("API_ENDPOINT");
    const data = await response.json();

使用 TypeScript

  • 定义数据类型以提高开发效率。

  • type Repository = {
      id: number;
      name: string;
      fullName: string;
    };

共享数据获取

  • 不仅可以在页面中获取数据,还可以在布局组件中获取数据。

  • 数据可以在布局中共享,供不同路由使用。

图片

图片

图片

3. 数据缓存与更新

静态数据

  • 默认情况下,所有数据获取都是静态的。

  • 行为:在生产构建时,数据会被缓存为静态内容。

动态数据

  • 通过 fetch 的 cache: "no-store" 参数,每次请求都重新获取数据。

const response = await fetch("API_ENDPOINT", { cache: "no-store" });

增量静态再生(ISR)

  • 使用 next.revalidate 参数设置数据重新验证时间间隔(如 5 秒)。

const response = await fetch("API_ENDPOINT", { next: { revalidate: 5 } });

结合静态和动态数据

  • 同一页面可以同时使用静态、动态和 ISR 数据获取策略。

4. 元数据(Metadata)

静态元数据

  • 定义方式:通过 metadata 对象定义页面的元数据。

  • export const metadata = {
      title: "My Page",
      description: "This is a description",
    };
  • 作用:生成 HTML 的 <title> 和 <meta> 标签,优化 SEO。

动态元数据

  • 使用 generateMetadata 函数生成动态元数据。

  • 接受 params 作为参数。

  • export async function generateMetadata({ params }) {
      const post = await fetchPost(params.id);
      return {
        title: post.title,
        description: post.description,
      };
    }
  • 支持动态路由段和数据获取逻辑。

重复使用数据获取逻辑

  • 数据获取逻辑可在 generateMetadata 和页面组件中重复使用。

总结

  • 新特性:

    • 改进的布局支持。

    • 动态与静态数据结合。

    • 更简洁的数据获取方式。

    • 功能更强的元数据 API。

  • 灵活性:

    • 同一页面中可以结合静态、动态和 ISR 数据获取策略。

    • 支持布局和页面间的数据共享。

  • SEO 改进:

    • 静态和动态元数据的定义更加灵活。

<think>我们正在处理一个关于Vue Router的问题:使用router.push导航到两个页面后,调用router.back返回时出现404错误。 根据用户描述,问题出现在Vue 3的Vue Router中。我们需要分析可能的原因并提供解决方案。 可能的原因: 1. 路由配置问题:可能没有配置404页面的捕获路由,或者路由配置不正确。 2. 历史记录管理问题:在使用router.push后,历史记录栈可能被破坏或状态异常。 3. 服务器配置问题:如果使用history模式,服务器没有正确配置以支持SPA(单页应用),导致在直接访问路由或返回时服务器返回404。 解决方案: 1. 检查路由配置:确保所有路由都被正确配置,特别是有一个捕获未匹配路径的路由(通配符路由)指向404页面。 2. 检查路由模式:Vue Router支持两种模式:hash模式和history模式。在history模式下,需要服务器配置支持,以避免404错误。 3. 服务器配置:如果使用history模式,确保服务器被配置为对于任何不匹配静态资源的请求都返回index.html。这样Vue应用才能接管路由。 具体步骤: 步骤1:检查路由配置 在路由配置文件中,应该有一个通配符路由来捕获404错误。例如: ```javascript const routes = [ // ...其他路由 { path: '/:pathMatch(.*)*', name: 'NotFound', component: NotFoundComponent } ]; ``` 步骤2:检查路由模式 在创建路由器实例时,如果使用history模式,需要指定模式: ```javascript import { createRouter, createWebHistory } from 'vue-router'; const router = createRouter({ history: createWebHistory(), routes }); ``` 但是,history模式需要服务器配置支持。 步骤3:服务器配置(以常见的服务器为例) - Nginx: ```nginx location / { try_files $uri $uri/ /index.html; } ``` - Apache: ```apache <IfModule mod_rewrite.c> RewriteEngine On RewriteBase / RewriteRule ^index\.html$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.html [L] </IfModule> ``` - 其他服务器(如Node.js, Express): ```javascript const express = require('express'); const history = require('connect-history-api-fallback'); const app = express(); app.use(history()); ``` 另外,用户提到在调用router.back时出现404,这意味着在返回时访问了一个在服务器上不存在的路径(在history模式下)。因此,确保服务器配置正确是关键。 如果问题仍然存在,检查是否有其他中间件或代码干扰了路由行为。 步骤4:检查代码中是否有异常操作 例如,是否在导航守卫中进行了重定向或取消了导航?检查是否有任何代码修改了历史记录栈。 步骤5:使用Vue Router提供的导航方法 确保在代码中正确使用router.push和router.back,避免混合使用原生history API(除非你知道如何正确处理)。 示例代码: 使用router.push导航: ```javascript router.push('/page1'); router.push('/page2'); ``` 然后使用router.back()返回,应该回到page1。 如果按照上述步骤检查后问题仍然存在,请提供更详细的代码和配置信息以便进一步排查。 相关问题: 1. Vue Router的history模式和hash模式有什么区别? 2. 如何在Vue Router中配置404页面? 3. 如何解决Vue Router在history模式下部署到服务器后的404问题? 4. Vue Router的导航守卫有哪些?如何使用? 5. 在Vue Router中,如何监听路由变化?</think>### Vue 3 Router 返回 404 错误的原因与解决方案 #### 问题原因分析 1. **路由模式未配置服务器支持** 使用 `createWebHistory()` 的 history 模式时,需服务器配置将所有请求重定向到 `index.html`。否则调用 `router.back()` 返回时,浏览器会直接请求服务器路径,导致 404 错误[^1][^2]。 2. **缺失通配符路由** 未配置捕获未匹配路径的路由规则,当返回的 URL 不在路由表中时,Vue Router 无法处理该路径。 3. **异步路由加载问题** 动态导入组件时(如 `component: () => import('./Page.vue')`),若返回时组件尚未加载完成,可能触发 404。 4. **导航守卫拦截** `beforeEach` 守卫中未正确处理返回逻辑,可能导致导航中断。 #### 解决方案 ##### 1. 服务器配置(关键步骤) **Nginx 配置示例**: ```nginx server { location / { try_files $uri $uri/ /index.html; # 所有请求重定向到 index.html } } ``` **Apache 配置**: ```apache <IfModule mod_rewrite.c> RewriteEngine On RewriteBase / RewriteRule ^index\.html$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.html [L] </IfModule> ``` ##### 2. 添加通配符路由 在路由配置中增加 404 处理: ```javascript const routes = [ // ...其他路由 { path: '/:pathMatch(.*)*', // 捕获所有未匹配路径 name: 'NotFound', component: () => import('./views/404.vue') } ]; ``` ##### 3. 检查导航守卫 确保守卫中调用 `next()` 放行返回操作: ```javascript router.beforeEach((to, from, next) => { // 示例:登录验证 if (to.meta.requiresAuth && !isLoggedIn) { next('/login'); // 重定向到登录页 } else { next(); // 必须调用 next() 放行导航 } }); ``` ##### 4. 验证路由模式 确认是否错误使用了 `createWebHashHistory()`(哈希模式无需服务器配置): ```javascript import { createRouter, createWebHistory } from 'vue-router'; const router = createRouter({ history: createWebHistory(), // ✅ 正确模式 routes }); ``` #### 调试建议 1. 使用 Vue Devtools 检查路由状态 2. 监听路由错误: ```javascript router.onError((error) => { console.error('路由错误:', error); }); ``` #### 替代方案 若无法修改服务器配置,可改用哈希模式(URL 带 `#`): ```javascript history: createWebHashHistory() // 无需服务器支持 ``` > **关键点**:history 模式必须配合服务器重定向规则,否则返回操作会触发实际 HTTP 请求导致 404[^1][^2]。 --- ### 相关问题 1. Vue Router 的 history 模式和 hash 模式有何本质区别? 2. 如何在导航守卫中实现路由重定向和权限控制? 3. Vue 3 中如何动态添加路由规则? 4. 路由懒加载对性能有何影响?如何优化? 5. 如何处理 Vue Router 的导航失败错误(如 `NavigationDuplicated`)? [^1]: 前端笔记(11) Vue3 Router 编程式导航 router.push router.replace [^2]: vue路由导航方法 router.push,router.replace,router.go,router.back,router.forward
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值