Next框架学习篇 ✅

++写在最前:好难啊我走召🤯🤯🤯++

目录&待解决的问题

next版本:13.5.1

node版本:22.15.0
🔗 Next中文文档

目录

[1️⃣ 页面](#1️⃣ 页面)
[2️⃣ 应用级路由](#2️⃣ 应用级路由)
[3️⃣ CSS相关](#3️⃣ CSS相关)

待解决的问题

[1️⃣ 如何做嵌套路由](#1️⃣ 如何做嵌套路由)
[2️⃣ 如何做动态路由表](#2️⃣ 如何做动态路由表)
[3️⃣ 如何集成mobx](#3️⃣ 如何集成mobx)
[4️⃣ 如何做客户端渲染](#4️⃣ 如何做客户端渲染)


页面

假设在 /next_project/pages/home.tsx下我们export default了这样一个组件:

ts 复制代码
const HomePage = () => {
  return <div>HomePage</div>;
};
export default HomePage;

此时我们便可以在本地的http://localhost:3000/home中查看此组件,这便是使用Next脚手架搭建的应用中最基础的页面与组件的映射关系。这种约定方式很像微信小程序开发,也很像Egg。

此外,Next具有静态生成服务端渲染 这两种预渲染 模式。静态生成是Next推荐的最佳实践,即指HTML在应用构建时生成,并在每次页面请求时通过浏览器缓存被复用(CDN可以在没有额外配置的情况下缓存静态生成的页面以提高性能);服务端渲染指的是在每次请求时重新生成HTML。

静态生成

默认情况下,Next.js 使用静态生成来预渲染页面,正如上述Demo所编写的那样。此外,Next官方的文档中还提供了需要外部数据的静态生成的页面 的做法,此处只将其与客户端渲染进行对比,因为煮啵始终觉得既然走到了"需要外部数据"这个份上了,那页面就具有实时性的需求,应该用服务端渲染或者客户端渲染才合理。 见下面Demo:

js 复制代码
import { useEffect, useState } from "react";
interface PageProps { posts: Array<{ title: string }> }

const UserPage = (props: PageProps) => {
  const { posts: postsA } = props; // postsA在Next静态生成时注入
  const [postsB, setPostsB] = useState<Array<{ title: string }>>([]);
  useEffect(() => {
    setPostsB([{ title: "Post 3" }, { title: "Post 4" }]);
  }, []);
  return (
    <div className="user-page">
      <h1>User Page</h1>
      {postsA.map((post) => <div>{post.title}</div>)}
      {postsB.map((post) => <div>{post.title}</div>)}
    </div>
  );
};

// 此函数会在构建的时候执行一次
export async function getStaticProps() {
  const result = await new Promise((res) => {
    const posts = [{ title: "Post 1" }, { title: "Post 2" }];
    res(posts);
  });
  return { props: { posts: result } };
}

export default UserPage;

Q1:"静态生成"生成的到底是啥玩意?
A1:生成的是"可预见的DOM"。 说了跟白说一样哈哈。 对比我们熟悉的用Vite构建的单页面应用或许更好理解,这种时候我们请求的HTML文件中通常只是一个id为root的div,这种HTML通常只是一个"空壳"。但是在Next的静态构建中我们请求的HTML文件中却出现了用postsA来填充的多个div,这部分DOM是不依赖于"水合"这个过程,就可以事先渲染出来的;但是用postsB来填充的多个div并没有出现在HTML文件中,其行为更像我们熟悉的"客户端渲染"。

区别 Next静态生成 Vite构建的SPA应用
HTML中是否含有页面实际内容 ✅ 有完整的UI内容 ❌ 通常只是一个id为root的div
首屏是否无需JS即可看到UI ✅ 可以,即使可能不完整 ❌ 看不到
是否能用SEO抓取 ✅ 很适合 ❌ 几乎抓不到
是否支持预渲染多页面 ✅ 多页面静态生成 ❌ 本质只有一个HTML + JS

服务端渲染

在Next中我们可以通过实现getServerSideProps函数来实现服务端渲染,详见下面的Demo:

ts 复制代码
const HomePage = ({ data }: any) => {
  return (
    <div>
      <div>name: {data.name}</div>
      <div>age: {data.age}</div>
    </div>
  );
}

export async function getServerSideProps() {
  // 每次请求页面时,都会执行此函数
  console.log("getServerSideProps");
  const result = await new Promise((res) => {
    const data = { name: "Pro", age: 25 };
    res(data);
  });
  console.log("result", result);
  return { props: { data: result } };
}

export default HomePage;

后续我们每次请求http://localhost:3000/home的时候,两次`console.log()`都是在服务端执行的(开发模式下即为VSCode),且每次对http://localhost:3000/home的请求返回的响应状态码都是200(说明是在请求时实时返回的,走不了缓存;如果用的是静态生成,从第二次请求开始返回的便是304)

需要重申的是,不管是静态生成的HTML还是服务端渲染后返回的HTML都可以依赖外部数据来填充HTML页面,具体做法可参考Next文档中此章的内容


应用级路由

路由嵌套 & 重定向

需求:想在Next中构建一个带左侧导航栏和右侧内容区的"后台管理布局",并通过导航切换子页面,如admin/dict和admin/notice,并将后台首页重定向到admin/notice。

直接开撸:

ts 复制代码
// pages/admin/index.tsx
import Link from "next/link";
import { ReactNode, useEffect } from "react";
import { useRouter } from "next/router";
export default function AdminLayout({ children }: { children: ReactNode }) {
  const router = useRouter();
  useEffect(() => {
    // 页面加载后立即跳转到公告管理
    router.pathname === "/admin" && router.replace("/admins/notice");
  }, []);
  return (
    <div style={{ display: "flex", height: "100vh" }}>
      {/* 左侧导航栏 */}
      <div style={{ width: 200, background: "#f2f2f2", padding: 20 }}>
        <nav style={{ display: "flex", flexDirection: "column", gap: 10 }}>
          <Link href="/admins/dict">词典管理</Link>
          <Link href="/admins/notice">公告管理</Link>
        </nav>
      </div>
      {/* 右侧内容 */}
      <div style={{ flex: 1, padding: 20 }}>{children}</div>
    </div>
  );
}

// pages/admin/notice.tsx
import AdminLayout from ".";
const NoticePage = () => {
  return <AdminLayout>Notice Page</AdminLayout>;
};
export default NoticePage;

// pages/admin/dict.tsx
import AdminLayout from ".";
const DictPage = () => {
  return <AdminLayout>Dict Manege</AdminLayout>;
};
export default DictPage;

路由守卫

虽然Next的路由是文件系统驱动的,且没有像react-router那样的显式路由表,但Next仍提供了多种路由守卫方式。但这部分内容的讨论脱离了煮啵想学的"服务端渲染"的内容,更偏向于实际开发的应用,后续开发到这中需求再详细补充,此处仅对几种组件内的守卫方法做简单介绍。其实就是懒。

控制方式 触发时机 用法举例 适用场景
页面组件内守卫 客户端 useEffect + 跳转 判断登陆态,客户端重定向
getServerSideProps 服务端 判断cookie/token,重定向或403 页面级SSR权限控制
Next中间件middleware.ts 请求到达前 在Edge上做重定向拦截 全局路径守卫,高性能

懒加载

Next已经实现了基于路由的自动懒加载 ,以上述Demo为例,只要还未进入到admin/dict页面,那么pages/admin/dict.tsx的代码便不会被加载。此处或许还有更高级的用法,后续见到了再补充吧。


CSS相关

有空再写


相关推荐
FanetheDivine13 分钟前
three.js学习笔记 2.光照和材质
react.js·three.js
PyAIGCMaster2 小时前
穷鬼计划:react+tailwindcss+vercel
前端·react.js·前端框架
JiangJiang16 小时前
🚀 React 弹窗还能这样写?手撸一个高质量 Modal 玩起来!
前端·javascript·react.js
t20071816 小时前
4.27 react第一天
前端·react.js·前端框架
溪i17 小时前
react-spring/web + children not defined
前端·spring·react.js
egghead2631617 小时前
trae+react+tailwindcss项目开发
前端·react.js
酱酱子耶17 小时前
async没有了await会发生什么?实际问题
前端·react.js
就是我19 小时前
React 应用性能优化实战
前端·react.js·性能优化
前端付豪19 小时前
🚀 React 应用国际化实战:深入掌握 react-i18next 的高级用法
前端·react.js·架构