Nextjs|React and Nextjs

什么是 React 和 Nextjs

在构建现代应用程序时,我们需要考虑一些事。如:

  • 用户界面 - 用户将如何使用您的应用程序并与之交互。
  • 路由 - 用户如何在应用程序的不同部分之间导航。
  • 数据获取 - 数据所在的位置以及如何获取数据。
  • 渲染 - 渲染静态或动态内容的时间和位置。
  • 集成 - 使用的第三方服务(用于 CMS、身份验证、支付等)以及如何进行对接。
  • 基础设施 - 部署、存储和运行应用程序代码(Serverless、CDN等)的地方。
  • 性能 - 如何为最终用户优化应用程序。
  • 可扩展性 - 应用程序如何随着团队、数据和流量的增长而适应。
  • 开发人员体验 - 团队在构建和维护应用程序方面的经验。

对于应用程序的每个部分,我们需要决定是自己实现解决方案还是使用现成的其他工具,例如包、库和框架。

简单概括React

React本身实际上是一个JS库,用于构建UI界面的JS库

React本身只提供了核心的API,对于如何使用等其他方面并未进行约束,这种方式有好有坏,好处是生态很好,基于React开发的框架和轮子很多。但是坏处就是有点像毛坯房,只提供了构建的基础,还需要额外约定配置路由等

也正因此,Nextjs就是基于React的、可以为开发者提供快速开发全栈应用程序的框架

Nextjs

框架是指 Next.js 处理 React 所需的工具和配置,并为应用程序提供额外的结构、功能和优化。

用户界面UI渲染

HTML和DOM

当用户访问网页时,服务器会向浏览器返回一个 HTML 文件

然后,浏览器读取 HTML 并构建文档对象模型 (DOM)

DOM 是 HTML 元素的对象表示形式。它充当代码和用户界面之间的桥梁,并具有具有父子关系的树状结构

我们可以通过原生的JS来监听用户事件并通过选择、添加、更新和删除用户界面中的特定元素来操作 DOM

DOM 操作不仅允许定位特定元素,还可以更改其样式和内容

至于DOM和HTML的区别,可以简单理解为,HTML可以直接看源代码,但是DOM是渲染JS解析后的完整内容

例如如下的html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<html>
<body>
<div id="app"></div>
<script type="text/javascript">
// Select the div element with 'app' id
const app = document.getElementById('app');

// Create a new H1 element
const header = document.createElement('h1');

// Create a new text node for the H1 element
const text = 'Develop. Preview. Ship.';
const headerContent = document.createTextNode(text);

// Append the text to the H1 element
header.appendChild(headerContent);

// Place the H1 element inside the div
app.appendChild(header);
</script>
</body>
</html>

直接在开发者工具中看到的HTML内容如下:

1
2
3
4
5
6
<html>
<body>
<div id="app"></div>
<script type="text/javascript">...</script>
</body>
</html>

但是DOM内容如下

1
2
3
4
5
6
7
8
<html>
<body>
<div id="app">
<h1>Develop, Preview, Ship.</h1>
</div>
<script type="text/javascript">...</script>
</body>
</html>

HTML 表示初始页面内容,而 DOM 表示编写的 JavaScript 代码更改的更新页面内容

命令式编程和声明式编程

原生JS虽然很强,但是太冗长了,业务规模增长,维护性也越来越差

此外上述JS原生写法实际上是一种命令式编程。所有的代码内容都是正在编写有关如何更新用户界面的步骤

但是,在构建用户界面时,通常首选声明式编程,因为它可以加快开发过程。如果开发人员能够声明他们想要显示的内容(在本例中是带有一些文本的标签),而不是必须编写 DOM 方法,这将很有帮助。

换句话说,命令式编程就像给厨师分步指导如何制作披萨。声明式编程就像订购披萨,而不关心制作披萨所需的步骤。

React就是一个声明式JS库,作为开发人员,我们告诉 React 希望用户界面发生什么,React 将为我们找出如何更新 DOM 的步骤

使用组件构建UI

React 三大核心概念:

  • 组件
  • Props
  • state

使用props

1
2
3
4
5
6
7
8
9
10
11
function HomePage() {
return (
<div>
<Header title="React" />
</div>
);
}

function Header(props) {
console.log(props); // 实际上这里不做任何处理的接收 props,默认是一个对象 {title: React}
}

这也是为什么我们一般都在子组件的入参中加上一对花括号,因为这本质上是在对象解构

1
2
3
function Header({ title }) {
return <div>{title}</div>;
}

运行Nextjs

基础环境

首先单个页面只能是组件,算不算框架

我们需要安装依赖

  • 新建工程目录
  • 新建package.json,内容写一个空对象即可
  • npm install react@latest react-dom@latest next@latest

运行后应该会自动安装依赖,package.json文件内容应该如下

1
2
3
4
5
6
7
{
"dependencies": {
"next": "^15.2.4",
"react": "^19.0.0",
"react-dom": "^19.0.0"
}
}

修改页面路由

将这个demo 放置在 /app 下,命名为page.jsx,所以应该是 /app/page.jsx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import {useState} from 'react';

function Header({title}) {
return <h1>{title ? title : 'Default title'}</h1>;
}

function HomePage() {
const names = ['Ada Lovelace', 'Grace Hopper', 'Margaret Hamilton'];

const [likes, setLikes] = useState(0);

function handleClick() {
setLikes(likes + 1);
}

return (
<div>
<Header title="Develop. Preview. Ship."/>
<ul>
{names.map((name) => (
<li key={name}>{name}</li>
))}
</ul>

<button onClick={handleClick}>Like ({likes})</button>
</div>
);
}

export default function HomePage(){}

启动服务端

将“next dev”脚本添加到 package.json 文件中

1
2
3
4
5
6
7
8
9
10
{
"scripts": {
"dev": "next dev"
},
"dependencies": {
"next": "^15.2.4",
"react": "^19.0.0",
"react-dom": "^19.0.0"
}
}

运行 npm run dev

不出意外的报错了:

Error: × You’re importing a component that needs useState. This React hook only works in a client component. To fix, mark the file (or its parent) with the "use client" directive.

这是因为 Next.js 使用了 React 服务器组件,这是一项允许 React 在服务器上渲染的新功能

而服务器组件不支持useState,因此您要改用客户端组件

这个问题后面会进行修复

layout

观察到在 app 目录下,自动生成了一个文件

1
2
3
4
5
6
7
8
9
10
11
12
export const metadata = {
title: 'Next.js',
description: 'Generated by Next.js',
};

export default function RootLayout({ children }) {
return (
<html lang="en">
<body>{children}</body>
</html>
);
}

这是应用程序的主要布局

我们可以使用它来添加所有页面共享的 UI 元素(例如导航、页脚等)

服务端组件和客户端组件

要了解服务器和客户端组件的工作原理,熟悉两个基础 Web 概念会很有帮助:

  • 应用程序代码可以在其中执行的环境分为两种:服务器和客户端。
  • 分隔服务器和客户端代码的网络边界。

客户端和服务端有各自的功能和约束:

  • 通过将渲染和数据提取移至服务器,您可以减少发送到客户端的代码量,从而提高应用程序的性能
  • 但是,要使 UI 具有交互性,您需要在客户端上更新 DOM

使用客户端组件

Next.js 默认使用服务器组件——这是为了提高应用程序的性能

回顾浏览器中的错误,Next.js 警告是,我们正在尝试在服务器组件中使用useState

我们可以通过将交互式“赞”按钮移至客户端组件来解决此问题。

新建一个文件标识点赞的组件

1
2
3
4
5
6
7
8
9
10
11
12
13
'use client'

import {useState} from "react";

export default function LikeButton() {
let [likes, setLikes] = useState(0)

function handleClick() {
setLikes(likes + 1);
}

return <button onClick={handleClick}>Like ({likes})</button>
}

要创建客户端组件,在文件顶部添加 React指令 'use client'。这告诉 React 在客户端上呈现组件

默认组件(服务端组件)也需要同步修改,删除 useState 引用,原先声明点赞按钮的地方调整为引入客户端组件即可


Nextjs|React and Nextjs
http://example.com/2025/03/28/Nextjs-React-and-Nextjs/
作者
Noctis64
发布于
2025年3月28日
许可协议