题目
题目:基于 Next.js 实现的服务端渲染博客页面
问题描述:
请使用 Next.js 构建一个简单的博客页面,页面将显示从外部 API 获取的博客文章数据。具体要求如下:
使用 getServerSideProps 获取并渲染从外部 API 获取的博客文章列表。
每篇文章包含标题和内容的简短摘要。
点击文章标题后,用户应被导航到一个 动态路由页面,展示该文章的完整内容。
在文章详情页中,实现一个 “返回” 按钮,用户可以点击此按钮返回到博客列表页面。
外部 API 示例:
您可以使用以下 API 模拟外部数据源:
url Copy code jsonplaceholder.typicode.com/posts>
该 API 返回的每篇文章数据格式为:
{
"userId": 1,
"id": 1,
"title": "文章标题",
"body": "文章内容"
}
要求:
使用 Next.js 的 getServerSideProps 实现服务端渲染,获取博客数据并渲染到页面中。
在博客列表页中,每篇文章只显示标题和内容的前 20 个字符作为摘要。
实现动态路由:点击文章标题后跳转到 /posts/[id] 动态路由页面,显示文章完整内容。
提供代码注释,并确保结构清晰。
思考
给大家一个思考的时间,看看遇到这样的面试题自己应该怎么写
我的思考逻辑:
-
创建nextjs项目
-
博客首页使用
getServerSideProps获取数据并使用useContext存储数据 -
动态路由进行跳转,
Nextjs也是支持的,获取数据并筛选。
创建Next.js项目
首先,确保你已经安装了 Next.js 和其他相关依赖。你可以通过以下命令创建一个新的 Next.js 项目:
npx create-next-app@latest next-blog
cd next-blog
npm install
创建Context
// context/PostContext.js
import { createContext, useContext, useState } from "react";
const PostContext = createContext();
export function PostProvider({ children }) {
const [posts, setPosts] = useState([]);
return (
<PostContext.Provider value={{ posts, setPosts }}>
{children}
</PostContext.Provider>
);
}
export function usePostContext() {
return useContext(PostContext);
}
在 _app.js 中包装全局状态
// pages/_app.js
import { PostProvider } from "../context/PostContext";
function MyApp({ Component, pageProps }) {
return (
<PostProvider>
<Component {...pageProps} />
</PostProvider>
);
}
export default MyApp;
在首页获取数据并存入 Context
// pages/index.js
import Link from "next/link";
import { usePostContext } from "../context/PostContext";
export default function Home({ postsData }) {
const { setPosts } = usePostContext();
// 存入 context
setPosts(postsData);
return (
<div>
<h1>Blog Posts</h1>
<ul>
{postsData.map((post) => (
<li key={post.id}>
<Link href={`/posts/${post.id}`}>
<a>
<h2>{post.title}</h2>
<p>{post.body.slice(0, 20)}...</p>
</a>
</Link>
</li>
))}
</ul>
</div>
);
}
export async function getServerSideProps() {
const res = await fetch("<https://jsonplaceholder.typicode.com/posts");
const postsData = await res.json();
return {
props: {
postsData,
},
};
}
在文章详情页中获取 Context 中的文章数据
// pages/posts/[id].js
import { useRouter } from "next/router";
import { usePostContext } from "../../context/PostContext";
import Link from "next/link";
export default function Post() {
const router = useRouter();
const { posts } = usePostContext();
const { id } = router.query;
const post = posts.find((p) => p.id.toString() === id);
if (!post) {
return <div>Post not found</div>;
}
return (
<div>
<h1>{post.title}</h1>
<p>{post.body}</p>
<Link href="/">
<a>← Back to home</a>
</Link>
</div>
);
}
目录结构
nextjs-blog/
├── components/
│ └── Navbar.js # 其他可复用的组件
├── context/
│ └── PostContext.js # 用于管理博客文章的全局状态
├── pages/
│ ├── posts/
│ │ └── [id].js # 动态路由页面,展示文章详情
│ ├── _app.js # 全局入口,注入 Context Provider
│ ├── index.js # 博客首页,显示文章列表
├── public/
│ └── favicon.ico # 公共资源文件
├── styles/
│ └── globals.css # 全局样式文件
├── package.json # 项目依赖文件
├── README.md # 项目说明文件
├── next.config.js # Next.js 配置文件
结尾
很简单吧,重点就是怎么传输我们获取的数据,当然除了useContext这种方法我们还有很多其他的方法可以使用。比如SessionStorage 或 LocalStorage、Redux、URL Hash、useRouter。
如果大家有任何疑问,欢迎随时在评论区提出,或者直接私聊我探讨交流!我非常愿意和大家一起讨论这些技术问题。如果我的解答有任何不准确的地方,也请大家及时指出,我会积极改正并完善内容。
你们的支持如同璀璨星光,照亮我前行的创作之路,让我更有信心和热情为大家带来更多优质的内容。